blob: 019c99ff6d825f4bd146ea762f0f5ab3c3b17493 [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
reed@google.comac10a2d2010-12-22 21:39:39 +000017#include "GrGpu.h"
18#include "GrMemory.h"
19#include "GrTextStrike.h"
20#include "GrTextureCache.h"
21#include "GrClipIterator.h"
22#include "GrIndexBuffer.h"
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000023#include "GrVertexBuffer.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000024#include "GrBufferAllocPool.h"
25
26// probably makes no sense for this to be less than a page
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +000027static const size_t VERTEX_POOL_VB_SIZE = 1 << 12;
28static const int VERTEX_POOL_VB_COUNT = 1;
reed@google.comac10a2d2010-12-22 21:39:39 +000029
30///////////////////////////////////////////////////////////////////////////////
31
32size_t GrTexture::BytesPerPixel(PixelConfig config) {
33 switch (config) {
34 case kAlpha_8_PixelConfig:
35 case kIndex_8_PixelConfig:
36 return 1;
37 case kRGB_565_PixelConfig:
38 case kRGBA_4444_PixelConfig:
39 return 2;
40 case kRGBA_8888_PixelConfig:
41 case kRGBX_8888_PixelConfig:
42 return 4;
43 default:
44 return 0;
45 }
46}
47
48bool GrTexture::PixelConfigIsOpaque(PixelConfig config) {
49 switch (config) {
50 case GrTexture::kRGB_565_PixelConfig:
51 case GrTexture::kRGBX_8888_PixelConfig:
52 return true;
53 default:
54 return false;
55 }
56}
57
58
59///////////////////////////////////////////////////////////////////////////////
60
61extern void gr_run_unittests();
62
63GrGpu::GrGpu() : f8bitPaletteSupport(false),
bsalomon@google.com1c13c962011-02-14 16:51:21 +000064 fCurrPoolVertexBuffer(NULL),
65 fCurrPoolStartVertex(0),
66 fCurrPoolIndexBuffer(NULL),
67 fCurrPoolStartIndex(0),
68 fVertexPool(NULL),
69 fIndexPool(NULL),
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000070 fQuadIndexBuffer(NULL),
71 fUnitSquareVertexBuffer(NULL) {
reed@google.comac10a2d2010-12-22 21:39:39 +000072#if GR_DEBUG
73// gr_run_unittests();
74#endif
75 resetStats();
76}
77
78GrGpu::~GrGpu() {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000079 GrSafeUnref(fQuadIndexBuffer);
80 GrSafeUnref(fUnitSquareVertexBuffer);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000081 delete fVertexPool;
82 delete fIndexPool;
reed@google.comac10a2d2010-12-22 21:39:39 +000083}
84
85void GrGpu::resetContext() {
86}
87
88void GrGpu::unimpl(const char msg[]) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +000089#if GR_DEBUG
90 GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
91#endif
reed@google.comac10a2d2010-12-22 21:39:39 +000092}
93
94///////////////////////////////////////////////////////////////////////////////
95
bsalomon@google.com1c13c962011-02-14 16:51:21 +000096static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1;
reed@google.comac10a2d2010-12-22 21:39:39 +000097
reed@google.com8195f672011-01-12 18:14:28 +000098GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
reed@google.comac10a2d2010-12-22 21:39:39 +000099
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000100static inline void fill_indices(uint16_t* indices, int quadCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000101 for (int i = 0; i < quadCount; ++i) {
102 indices[6 * i + 0] = 4 * i + 0;
103 indices[6 * i + 1] = 4 * i + 1;
104 indices[6 * i + 2] = 4 * i + 2;
105 indices[6 * i + 3] = 4 * i + 0;
106 indices[6 * i + 4] = 4 * i + 2;
107 indices[6 * i + 5] = 4 * i + 3;
108 }
109}
110
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000111const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000112 if (NULL == fQuadIndexBuffer) {
113 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
114 GrGpu* me = const_cast<GrGpu*>(this);
115 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
116 if (NULL != fQuadIndexBuffer) {
117 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
118 if (NULL != indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000119 fill_indices(indices, MAX_QUADS);
reed@google.comac10a2d2010-12-22 21:39:39 +0000120 fQuadIndexBuffer->unlock();
121 } else {
122 indices = (uint16_t*)GrMalloc(SIZE);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000123 fill_indices(indices, MAX_QUADS);
reed@google.comac10a2d2010-12-22 21:39:39 +0000124 if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
125 fQuadIndexBuffer->unref();
126 fQuadIndexBuffer = NULL;
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000127 GrCrash("Can't get indices into buffer!");
reed@google.comac10a2d2010-12-22 21:39:39 +0000128 }
129 GrFree(indices);
130 }
131 }
132 }
133
134 return fQuadIndexBuffer;
135}
136
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000137const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000138 if (NULL == fUnitSquareVertexBuffer) {
139
140 static const GrPoint DATA[] = {
141 GrPoint(0, 0),
142 GrPoint(GR_Scalar1,0),
143 GrPoint(GR_Scalar1,GR_Scalar1),
144 GrPoint(0, GR_Scalar1)
145 };
146 static const size_t SIZE = sizeof(DATA);
147
148 GrGpu* me = const_cast<GrGpu*>(this);
149 fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false);
150 if (NULL != fUnitSquareVertexBuffer) {
151 if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) {
152 fUnitSquareVertexBuffer->unref();
153 fUnitSquareVertexBuffer = NULL;
154 GrCrash("Can't get vertices into buffer!");
155 }
156 }
157 }
158
159 return fUnitSquareVertexBuffer;
160}
161
reed@google.comac10a2d2010-12-22 21:39:39 +0000162///////////////////////////////////////////////////////////////////////////////
163
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000164void GrGpu::clipWillBeSet(const GrClip& newClip) {
165 if (newClip != fClip) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000166 fClipState.fClipIsDirty = true;
167 }
168}
169
bsalomon@google.comffca4002011-02-22 20:34:01 +0000170bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000171 const GrIRect* r = NULL;
172
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000173 // we check this early because we need a valid
174 // render target to setup stencil clipping
175 // before even going into flushGraphicsState
176 if (NULL == fCurrDrawState.fRenderTarget) {
177 GrAssert(!"No render target bound.");
178 return false;
179 }
180
reed@google.comac10a2d2010-12-22 21:39:39 +0000181 if (fCurrDrawState.fFlagBits & kClip_StateBit) {
182 fClipState.fClipInStencil = fClip.countRects() > 1;
183
184 if (fClipState.fClipInStencil &&
185 (fClipState.fClipIsDirty ||
186 fClipState.fStencilClipTarget != fCurrDrawState.fRenderTarget)) {
187
188 AutoStateRestore asr(this);
189 AutoGeometrySrcRestore agsr(this);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000190
191 // We have to use setVertexSourceToBuffer (and index) in order
192 // to ensure we correctly restore the client's geom sources.
193 // We tack the clip verts onto the vertex pool but we don't
194 // use the various helper functions because of their side effects.
reed@google.comac10a2d2010-12-22 21:39:39 +0000195
196 int rectTotal = fClip.countRects();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000197 if (NULL == fVertexPool) {
198 fVertexPool = new GrVertexBufferAllocPool(this,
199 true,
200 VERTEX_POOL_VB_SIZE,
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +0000201 VERTEX_POOL_VB_COUNT);
202 } else if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
203 // we can't reset if vertex source is array or reserved
204 // because then the client data is in the pool!
205 fVertexPool->reset();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000206 }
207 const GrVertexBuffer* vertexBuffer;
208 int vStart;
209 GrPoint* rectVertices =
210 reinterpret_cast<GrPoint*>(fVertexPool->makeSpace(0,
211 rectTotal * 4,
212 &vertexBuffer,
213 &vStart));
214 for (int r = 0; r < rectTotal; ++r) {
215 const GrIRect& rect = fClip.getRects()[r];
216 rectVertices[4 * r].setIRectFan(rect.fLeft, rect.fTop,
217 rect.fRight, rect.fBottom);
218 }
219 fVertexPool->unlock();
220 this->setVertexSourceToBuffer(0, vertexBuffer);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000221 this->setIndexSourceToBuffer(getQuadIndexBuffer());
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000222 this->setViewMatrix(GrMatrix::I());
223 // don't clip the clip or recurse!
224 this->disableState(kClip_StateBit);
225 this->eraseStencilClip();
226 this->setStencilPass((GrDrawTarget::StencilPass)kSetClip_StencilPass);
reed@google.comac10a2d2010-12-22 21:39:39 +0000227 int currRect = 0;
228 while (currRect < rectTotal) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000229 int rectCount = GrMin(MAX_QUADS,
reed@google.comac10a2d2010-12-22 21:39:39 +0000230 rectTotal - currRect);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000231 this->drawIndexed(kTriangles_PrimitiveType,
232 vStart + currRect * 4,
233 0,
234 rectCount*4,
235 rectCount*6);
reed@google.comac10a2d2010-12-22 21:39:39 +0000236 currRect += rectCount;
237 }
238 fClipState.fStencilClipTarget = fCurrDrawState.fRenderTarget;
239 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000240
reed@google.comac10a2d2010-12-22 21:39:39 +0000241 fClipState.fClipIsDirty = false;
242 if (!fClipState.fClipInStencil) {
243 r = &fClip.getBounds();
244 }
245 }
246 // Must flush the scissor after graphics state
247 if (!flushGraphicsState(type)) {
248 return false;
249 }
250 flushScissor(r);
251 return true;
252}
253
254
255///////////////////////////////////////////////////////////////////////////////
256
bsalomon@google.comffca4002011-02-22 20:34:01 +0000257void GrGpu::drawIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000258 int startVertex,
259 int startIndex,
260 int vertexCount,
261 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000262 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
263 fReservedGeometry.fLocked);
264 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
265 fReservedGeometry.fLocked);
266
267 if (!setupClipAndFlushState(type)) {
268 return;
269 }
270
271#if GR_COLLECT_STATS
272 fStats.fVertexCnt += vertexCount;
273 fStats.fIndexCnt += indexCount;
274 fStats.fDrawCnt += 1;
275#endif
276
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000277 int sVertex = startVertex;
278 int sIndex = startIndex;
279 setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000280
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000281 drawIndexedHelper(type, sVertex, sIndex,
reed@google.comac10a2d2010-12-22 21:39:39 +0000282 vertexCount, indexCount);
283}
284
bsalomon@google.comffca4002011-02-22 20:34:01 +0000285void GrGpu::drawNonIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000286 int startVertex,
287 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000288 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
289 fReservedGeometry.fLocked);
290
291 if (!setupClipAndFlushState(type)) {
292 return;
293 }
294#if GR_COLLECT_STATS
295 fStats.fVertexCnt += vertexCount;
296 fStats.fDrawCnt += 1;
297#endif
298
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000299 int sVertex = startVertex;
300 setupGeometry(&sVertex, NULL, vertexCount, 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000301
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000302 drawNonIndexedHelper(type, sVertex, vertexCount);
303}
304
305void GrGpu::finalizeReservedVertices() {
306 GrAssert(NULL != fVertexPool);
307 fVertexPool->unlock();
308}
309
310void GrGpu::finalizeReservedIndices() {
311 GrAssert(NULL != fIndexPool);
312 fIndexPool->unlock();
313}
314
315void GrGpu::prepareVertexPool() {
316 if (NULL == fVertexPool) {
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +0000317 fVertexPool = new GrVertexBufferAllocPool(this, true,
318 VERTEX_POOL_VB_SIZE,
319 VERTEX_POOL_VB_COUNT);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000320 } else {
321 fVertexPool->reset();
322 }
323}
324
325void GrGpu::prepareIndexPool() {
326 if (NULL == fVertexPool) {
327 fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
328 } else {
329 fIndexPool->reset();
330 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000331}
332
333bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
334 void** vertices,
335 void** indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000336 GrAssert(!fReservedGeometry.fLocked);
337 size_t reservedVertexSpace = 0;
338
339 if (fReservedGeometry.fVertexCount) {
340 GrAssert(NULL != vertices);
341
342 prepareVertexPool();
343
344 *vertices = fVertexPool->makeSpace(vertexLayout,
345 fReservedGeometry.fVertexCount,
346 &fCurrPoolVertexBuffer,
347 &fCurrPoolStartVertex);
348 if (NULL == *vertices) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000349 return false;
350 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000351 reservedVertexSpace = VertexSize(vertexLayout) *
352 fReservedGeometry.fVertexCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000353 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000354 if (fReservedGeometry.fIndexCount) {
355 GrAssert(NULL != indices);
356
357 prepareIndexPool();
358
359 *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
360 &fCurrPoolIndexBuffer,
361 &fCurrPoolStartIndex);
362 if (NULL == *indices) {
363 fVertexPool->putBack(reservedVertexSpace);
364 fCurrPoolVertexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000365 return false;
366 }
367 }
368 return true;
369}
370
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000371void GrGpu::releaseGeometryHelper() {}
372
373void GrGpu::setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount) {
374 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
375 prepareVertexPool();
376#if GR_DEBUG
377 bool success =
378#endif
379 fVertexPool->appendVertices(fGeometrySrc.fVertexLayout,
380 vertexCount,
381 vertexArray,
382 &fCurrPoolVertexBuffer,
383 &fCurrPoolStartVertex);
384 GR_DEBUGASSERT(success);
385}
386
387void GrGpu::setIndexSourceToArrayHelper(const void* indexArray, int indexCount) {
388 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
389 prepareIndexPool();
390#if GR_DEBUG
391 bool success =
392#endif
393 fIndexPool->appendIndices(indexCount,
394 indexArray,
395 &fCurrPoolIndexBuffer,
396 &fCurrPoolStartIndex);
397 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000398}
399
400///////////////////////////////////////////////////////////////////////////////
401
402const GrGpu::Stats& GrGpu::getStats() const {
403 return fStats;
404}
405
406void GrGpu::resetStats() {
407 memset(&fStats, 0, sizeof(fStats));
408}
409
410void GrGpu::printStats() const {
411 if (GR_COLLECT_STATS) {
412 GrPrintf(
413 "-v-------------------------GPU STATS----------------------------v-\n"
414 "Stats collection is: %s\n"
415 "Draws: %04d, Verts: %04d, Indices: %04d\n"
416 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
417 "TexCreates: %04d, RTCreates:%04d\n"
418 "-^--------------------------------------------------------------^-\n",
419 (GR_COLLECT_STATS ? "ON" : "OFF"),
420 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
421 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
422 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
423 }
424}
425
426////////////////////////////////////////////////////////////////////////////////
427
428GrTexture::~GrTexture() {
429 // use this to set a break-point if needed
430// Gr_clz(3);
431}
432
433const GrSamplerState GrSamplerState::gClampNoFilter(
434 GrSamplerState::kClamp_WrapMode,
435 GrSamplerState::kClamp_WrapMode,
436 GrSamplerState::kNormal_SampleMode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000437 GrMatrix::I(),
reed@google.comac10a2d2010-12-22 21:39:39 +0000438 false);
439
440
441
442