blob: c48bd198920010cdaf1339d9c0a2b1ae0b531329 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "GrGpu.h"
19#include "GrMemory.h"
20#include "GrTextStrike.h"
21#include "GrTextureCache.h"
22#include "GrClipIterator.h"
23#include "GrIndexBuffer.h"
24
25///////////////////////////////////////////////////////////////////////////////
26
27size_t GrTexture::BytesPerPixel(PixelConfig config) {
28 switch (config) {
29 case kAlpha_8_PixelConfig:
30 case kIndex_8_PixelConfig:
31 return 1;
32 case kRGB_565_PixelConfig:
33 case kRGBA_4444_PixelConfig:
34 return 2;
35 case kRGBA_8888_PixelConfig:
36 case kRGBX_8888_PixelConfig:
37 return 4;
38 default:
39 return 0;
40 }
41}
42
43bool GrTexture::PixelConfigIsOpaque(PixelConfig config) {
44 switch (config) {
45 case GrTexture::kRGB_565_PixelConfig:
46 case GrTexture::kRGBX_8888_PixelConfig:
47 return true;
48 default:
49 return false;
50 }
51}
52
53
54///////////////////////////////////////////////////////////////////////////////
55
56extern void gr_run_unittests();
57
58GrGpu::GrGpu() : f8bitPaletteSupport(false),
59 fNPOTTextureSupport(kNone_NPOTTextureType),
60 fQuadIndexBuffer(NULL) {
61#if GR_DEBUG
62// gr_run_unittests();
63#endif
64 resetStats();
65}
66
67GrGpu::~GrGpu() {
68 if (NULL != fQuadIndexBuffer) {
69 fQuadIndexBuffer->unref();
70 }
71}
72
73void GrGpu::resetContext() {
74}
75
76void GrGpu::unimpl(const char msg[]) {
77// GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
78}
79
80///////////////////////////////////////////////////////////////////////////////
81
82bool GrGpu::canDisableBlend() const {
83 if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
84 (kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
85 return true;
86 }
87
88 // If we have vertex color without alpha then we can't force blend off
89 if ((fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) ||
90 0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
91 return false;
92 }
93
94 // If the src coef will always be 1...
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000095 if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend &&
96 kOne_BlendCoeff != fCurrDrawState.fSrcBlend) {
97 return false;
98 }
reed@google.comac10a2d2010-12-22 21:39:39 +000099
100 // ...and the dst coef is always 0...
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000101 if (kISA_BlendCoeff != fCurrDrawState.fDstBlend &&
102 kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
103 return false;
104 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000105
106 // ...and there isn't a texture with an alpha channel...
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000107 for (int s = 0; s < kNumStages; ++s) {
108 if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) {
109 GrAssert(NULL != fCurrDrawState.fTextures[s]);
110 GrTexture::PixelConfig config = fCurrDrawState.fTextures[s]->config();
111
112 if (GrTexture::kRGB_565_PixelConfig != config &&
113 GrTexture::kRGBX_8888_PixelConfig != config) {
114 return false;
115 }
116 }
117 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000118
119 // ...then we disable blend.
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000120 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000121}
122
123///////////////////////////////////////////////////////////////////////////////
124
125static const int MAX_QUADS = 512; // max possible: (1 << 14) - 1;
126
reed@google.com8195f672011-01-12 18:14:28 +0000127GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
reed@google.comac10a2d2010-12-22 21:39:39 +0000128
129static inline void fillIndices(uint16_t* indices, int quadCount) {
130 for (int i = 0; i < quadCount; ++i) {
131 indices[6 * i + 0] = 4 * i + 0;
132 indices[6 * i + 1] = 4 * i + 1;
133 indices[6 * i + 2] = 4 * i + 2;
134 indices[6 * i + 3] = 4 * i + 0;
135 indices[6 * i + 4] = 4 * i + 2;
136 indices[6 * i + 5] = 4 * i + 3;
137 }
138}
139
140const GrIndexBuffer* GrGpu::quadIndexBuffer() const {
141 if (NULL == fQuadIndexBuffer) {
142 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
143 GrGpu* me = const_cast<GrGpu*>(this);
144 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
145 if (NULL != fQuadIndexBuffer) {
146 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
147 if (NULL != indices) {
148 fillIndices(indices, MAX_QUADS);
149 fQuadIndexBuffer->unlock();
150 } else {
151 indices = (uint16_t*)GrMalloc(SIZE);
152 fillIndices(indices, MAX_QUADS);
153 if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
154 fQuadIndexBuffer->unref();
155 fQuadIndexBuffer = NULL;
156 GrAssert(!"Can't get indices into buffer!");
157 }
158 GrFree(indices);
159 }
160 }
161 }
162
163 return fQuadIndexBuffer;
164}
165
166int GrGpu::maxQuadsInIndexBuffer() const {
167 return (NULL == this->quadIndexBuffer()) ? 0 : MAX_QUADS;
168}
169
170///////////////////////////////////////////////////////////////////////////////
171
172void GrGpu::clipWillChange(const GrClip& clip) {
173 if (clip != fClip) {
174 fClipState.fClipIsDirty = true;
175 }
176}
177
178bool GrGpu::setupClipAndFlushState(PrimitiveType type) {
179 const GrIRect* r = NULL;
180
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000181 // we check this early because we need a valid
182 // render target to setup stencil clipping
183 // before even going into flushGraphicsState
184 if (NULL == fCurrDrawState.fRenderTarget) {
185 GrAssert(!"No render target bound.");
186 return false;
187 }
188
reed@google.comac10a2d2010-12-22 21:39:39 +0000189 if (fCurrDrawState.fFlagBits & kClip_StateBit) {
190 fClipState.fClipInStencil = fClip.countRects() > 1;
191
192 if (fClipState.fClipInStencil &&
193 (fClipState.fClipIsDirty ||
194 fClipState.fStencilClipTarget != fCurrDrawState.fRenderTarget)) {
195
196 AutoStateRestore asr(this);
197 AutoGeometrySrcRestore agsr(this);
198 this->disableState(kClip_StateBit);
199 eraseStencilClip();
200
201 int rectTotal = fClip.countRects();
202 static const int PtsPerRect = 4;
203 // this may be called while geometry is already reserved by the
204 // client. So we use our own vertex array where we avoid malloc
205 // if we have 4 or fewer rects.
206 GrAutoSTMalloc<PtsPerRect * 4, GrPoint> vertices(PtsPerRect *
207 rectTotal);
208 this->setVertexSourceToArray(vertices.get(), 0);
209 int currRect = 0;
210 while (currRect < rectTotal) {
211 int rectCount = GrMin(this->maxQuadsInIndexBuffer(),
212 rectTotal - currRect);
213
214 GrPoint* verts = (GrPoint*)vertices +
215 (currRect * PtsPerRect);
216
217 for (int i = 0; i < rectCount; i++) {
218 GrRect r(fClip.getRects()[i + currRect]);
219 verts = r.setRectFan(verts);
220 }
221 this->setIndexSourceToBuffer(quadIndexBuffer());
222
223 this->setViewMatrix(GrMatrix::I());
224 this->setStencilPass((GrDrawTarget::StencilPass)kSetClip_StencilPass);
225 this->drawIndexed(GrGpu::kTriangles_PrimitiveType,
226 currRect * PtsPerRect, 0,
227 rectCount * PtsPerRect, rectCount * 6);
228
229 currRect += rectCount;
230 }
231 fClipState.fStencilClipTarget = fCurrDrawState.fRenderTarget;
232 }
233 fClipState.fClipIsDirty = false;
234 if (!fClipState.fClipInStencil) {
235 r = &fClip.getBounds();
236 }
237 }
238 // Must flush the scissor after graphics state
239 if (!flushGraphicsState(type)) {
240 return false;
241 }
242 flushScissor(r);
243 return true;
244}
245
246
247///////////////////////////////////////////////////////////////////////////////
248
249void GrGpu::drawIndexed(PrimitiveType type,
250 uint32_t startVertex,
251 uint32_t startIndex,
252 uint32_t vertexCount,
253 uint32_t indexCount) {
254 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
255 fReservedGeometry.fLocked);
256 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
257 fReservedGeometry.fLocked);
258
259 if (!setupClipAndFlushState(type)) {
260 return;
261 }
262
263#if GR_COLLECT_STATS
264 fStats.fVertexCnt += vertexCount;
265 fStats.fIndexCnt += indexCount;
266 fStats.fDrawCnt += 1;
267#endif
268
269 setupGeometry(startVertex, startIndex, vertexCount, indexCount);
270
271 drawIndexedHelper(type, startVertex, startIndex,
272 vertexCount, indexCount);
273}
274
275void GrGpu::drawNonIndexed(PrimitiveType type,
276 uint32_t startVertex,
277 uint32_t vertexCount) {
278 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
279 fReservedGeometry.fLocked);
280
281 if (!setupClipAndFlushState(type)) {
282 return;
283 }
284#if GR_COLLECT_STATS
285 fStats.fVertexCnt += vertexCount;
286 fStats.fDrawCnt += 1;
287#endif
288
289 setupGeometry(startVertex, 0, vertexCount, 0);
290
291 drawNonIndexedHelper(type, startVertex, vertexCount);
292}
293
294bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
295 void** vertices,
296 void** indices) {
297 GrAssert((fReservedGeometry.fVertexCount == 0) ||
298 (NULL != vertices));
299 if (NULL != vertices) {
300 *vertices = fVertices.realloc(VertexSize(vertexLayout) *
301 fReservedGeometry.fVertexCount);
302 if (!*vertices && fReservedGeometry.fVertexCount) {
303 return false;
304 }
305 }
306 GrAssert((fReservedGeometry.fIndexCount == 0) ||
307 (NULL != indices));
308 if (NULL != indices) {
309 *indices = fIndices.realloc(sizeof(uint16_t) *
310 fReservedGeometry.fIndexCount);
311 if (!*indices && fReservedGeometry.fIndexCount) {
312 return false;
313 }
314 }
315 return true;
316}
317
318void GrGpu::releaseGeometryHelper() {
319 return;
320}
321
322///////////////////////////////////////////////////////////////////////////////
323
324const GrGpu::Stats& GrGpu::getStats() const {
325 return fStats;
326}
327
328void GrGpu::resetStats() {
329 memset(&fStats, 0, sizeof(fStats));
330}
331
332void GrGpu::printStats() const {
333 if (GR_COLLECT_STATS) {
334 GrPrintf(
335 "-v-------------------------GPU STATS----------------------------v-\n"
336 "Stats collection is: %s\n"
337 "Draws: %04d, Verts: %04d, Indices: %04d\n"
338 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
339 "TexCreates: %04d, RTCreates:%04d\n"
340 "-^--------------------------------------------------------------^-\n",
341 (GR_COLLECT_STATS ? "ON" : "OFF"),
342 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
343 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
344 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
345 }
346}
347
348////////////////////////////////////////////////////////////////////////////////
349
350GrTexture::~GrTexture() {
351 // use this to set a break-point if needed
352// Gr_clz(3);
353}
354
355const GrSamplerState GrSamplerState::gClampNoFilter(
356 GrSamplerState::kClamp_WrapMode,
357 GrSamplerState::kClamp_WrapMode,
358 GrSamplerState::kNormal_SampleMode,
359 false);
360
361
362
363