blob: f42e316082e2a3ec7484f4d5088bbe86b94bb557 [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"
bsalomon@google.comd302f142011-03-03 13:54:13 +000025#include "GrPathRenderer.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000026
27// probably makes no sense for this to be less than a page
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +000028static const size_t VERTEX_POOL_VB_SIZE = 1 << 12;
29static const int VERTEX_POOL_VB_COUNT = 1;
reed@google.comac10a2d2010-12-22 21:39:39 +000030
bsalomon@google.comd302f142011-03-03 13:54:13 +000031////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000032
33size_t GrTexture::BytesPerPixel(PixelConfig config) {
34 switch (config) {
35 case kAlpha_8_PixelConfig:
36 case kIndex_8_PixelConfig:
37 return 1;
38 case kRGB_565_PixelConfig:
39 case kRGBA_4444_PixelConfig:
40 return 2;
41 case kRGBA_8888_PixelConfig:
42 case kRGBX_8888_PixelConfig:
43 return 4;
44 default:
45 return 0;
46 }
47}
48
49bool GrTexture::PixelConfigIsOpaque(PixelConfig config) {
50 switch (config) {
51 case GrTexture::kRGB_565_PixelConfig:
52 case GrTexture::kRGBX_8888_PixelConfig:
53 return true;
54 default:
55 return false;
56 }
57}
58
59
bsalomon@google.comd302f142011-03-03 13:54:13 +000060////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000061
62extern void gr_run_unittests();
63
64GrGpu::GrGpu() : f8bitPaletteSupport(false),
bsalomon@google.com1c13c962011-02-14 16:51:21 +000065 fCurrPoolVertexBuffer(NULL),
66 fCurrPoolStartVertex(0),
67 fCurrPoolIndexBuffer(NULL),
68 fCurrPoolStartIndex(0),
69 fVertexPool(NULL),
70 fIndexPool(NULL),
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000071 fQuadIndexBuffer(NULL),
bsalomon@google.comd302f142011-03-03 13:54:13 +000072 fUnitSquareVertexBuffer(NULL),
73 fPathRenderer(NULL),
74 fVertexPoolInUse(false),
75 fIndexPoolInUse(false) {
reed@google.comac10a2d2010-12-22 21:39:39 +000076#if GR_DEBUG
77// gr_run_unittests();
78#endif
79 resetStats();
80}
81
82GrGpu::~GrGpu() {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000083 GrSafeUnref(fQuadIndexBuffer);
84 GrSafeUnref(fUnitSquareVertexBuffer);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000085 delete fVertexPool;
86 delete fIndexPool;
bsalomon@google.comd302f142011-03-03 13:54:13 +000087 delete fPathRenderer;
reed@google.comac10a2d2010-12-22 21:39:39 +000088}
89
90void GrGpu::resetContext() {
91}
92
93void GrGpu::unimpl(const char msg[]) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +000094#if GR_DEBUG
95 GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
96#endif
reed@google.comac10a2d2010-12-22 21:39:39 +000097}
98
bsalomon@google.comd302f142011-03-03 13:54:13 +000099////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000100
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000101static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000102
reed@google.com8195f672011-01-12 18:14:28 +0000103GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
reed@google.comac10a2d2010-12-22 21:39:39 +0000104
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000105static inline void fill_indices(uint16_t* indices, int quadCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000106 for (int i = 0; i < quadCount; ++i) {
107 indices[6 * i + 0] = 4 * i + 0;
108 indices[6 * i + 1] = 4 * i + 1;
109 indices[6 * i + 2] = 4 * i + 2;
110 indices[6 * i + 3] = 4 * i + 0;
111 indices[6 * i + 4] = 4 * i + 2;
112 indices[6 * i + 5] = 4 * i + 3;
113 }
114}
115
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000116const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000117 if (NULL == fQuadIndexBuffer) {
118 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
119 GrGpu* me = const_cast<GrGpu*>(this);
120 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
121 if (NULL != fQuadIndexBuffer) {
122 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
123 if (NULL != indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000124 fill_indices(indices, MAX_QUADS);
reed@google.comac10a2d2010-12-22 21:39:39 +0000125 fQuadIndexBuffer->unlock();
126 } else {
127 indices = (uint16_t*)GrMalloc(SIZE);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000128 fill_indices(indices, MAX_QUADS);
reed@google.comac10a2d2010-12-22 21:39:39 +0000129 if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
130 fQuadIndexBuffer->unref();
131 fQuadIndexBuffer = NULL;
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000132 GrCrash("Can't get indices into buffer!");
reed@google.comac10a2d2010-12-22 21:39:39 +0000133 }
134 GrFree(indices);
135 }
136 }
137 }
138
139 return fQuadIndexBuffer;
140}
141
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000142const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000143 if (NULL == fUnitSquareVertexBuffer) {
144
145 static const GrPoint DATA[] = {
146 GrPoint(0, 0),
147 GrPoint(GR_Scalar1,0),
148 GrPoint(GR_Scalar1,GR_Scalar1),
149 GrPoint(0, GR_Scalar1)
150 };
151 static const size_t SIZE = sizeof(DATA);
152
153 GrGpu* me = const_cast<GrGpu*>(this);
154 fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false);
155 if (NULL != fUnitSquareVertexBuffer) {
156 if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) {
157 fUnitSquareVertexBuffer->unref();
158 fUnitSquareVertexBuffer = NULL;
159 GrCrash("Can't get vertices into buffer!");
160 }
161 }
162 }
163
164 return fUnitSquareVertexBuffer;
165}
166
bsalomon@google.comd302f142011-03-03 13:54:13 +0000167////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000168
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000169void GrGpu::clipWillBeSet(const GrClip& newClip) {
170 if (newClip != fClip) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000171 fClipState.fClipIsDirty = true;
172 }
173}
174
bsalomon@google.comd302f142011-03-03 13:54:13 +0000175////////////////////////////////////////////////////////////////////////////////
176
177// stencil settings to use when clip is in stencil
178const GrStencilSettings GrGpu::gClipStencilSettings = {
179 kKeep_StencilOp, kKeep_StencilOp,
180 kKeep_StencilOp, kKeep_StencilOp,
181 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
182 0, 0,
183 0, 0,
184 0, 0
185};
186
187// converts special stencil func to
188static const GrStencilFunc gGrClipToNormalStencilFunc[2][kClipStencilFuncCount] = {
189 {// Stencil-Clipping is DISABLED, effectively always inside the clip
190 // In the Clip Funcs
191 kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc
192 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc
193 kLess_StencilFunc, // kLessIfInClip_StencilFunc
194 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc
195 // Special in the clip func that forces user's ref to be 0.
196 kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc
197 // make ref 0 and do normal nequal.
198 },
199 {// Stencil-Clipping is ENABLED
200 // In the Clip Funcs
201 kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc
202 // eq stencil clip bit, mask
203 // out user bits.
204
205 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc
206 // add stencil bit to mask and ref
207
208 kLess_StencilFunc, // kLessIfInClip_StencilFunc
209 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc
210 // for both of these we can add
211 // the clip bit to the mask and
212 // ref and compare as normal
213 // Special in the clip func that forces user's ref to be 0.
214 kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc
215 // make ref have only the clip bit set
216 // and make comparison be less
217 // 10..0 < 1..user_bits..
218 }
219};
220
221GrStencilFunc GrGpu::ConvertStencilFunc(bool stencilInClip, GrStencilFunc func) {
222 GrAssert(func >= 0);
223 if (func >= kBasicStencilFuncCount) {
224 GrAssert(func < kStencilFuncCount);
225 func = gGrClipToNormalStencilFunc[stencilInClip ? 1 : 0][func - kBasicStencilFuncCount];
226 GrAssert(func >= 0 && func < kBasicStencilFuncCount);
227 }
228 return func;
229}
230
231void GrGpu::ConvertStencilFuncAndMask(GrStencilFunc func,
232 bool clipInStencil,
233 unsigned int clipBit,
234 unsigned int userBits,
235 unsigned int* ref,
236 unsigned int* mask) {
237 if (func < kBasicStencilFuncCount) {
238 *mask &= userBits;
239 *ref &= userBits;
240 } else {
241 if (clipInStencil) {
242 switch (func) {
243 case kAlwaysIfInClip_StencilFunc:
244 *mask = clipBit;
245 *ref = clipBit;
246 break;
247 case kEqualIfInClip_StencilFunc:
248 case kLessIfInClip_StencilFunc:
249 case kLEqualIfInClip_StencilFunc:
250 *mask = (*mask & userBits) | clipBit;
251 *ref = (*ref & userBits) | clipBit;
252 break;
253 case kNonZeroIfInClip_StencilFunc:
254 *mask = (*mask & userBits) | clipBit;
255 *ref = clipBit;
256 break;
257 default:
258 GrCrash("Unknown stencil func");
259 }
260 } else {
261 *mask &= userBits;
262 *ref &= userBits;
263 }
264 }
265}
266
267////////////////////////////////////////////////////////////////////////////////
268
269#define VISUALIZE_COMPLEX_CLIP 0
270
271#if VISUALIZE_COMPLEX_CLIP
272 #include "GrRandom.h"
273 GrRandom gRandom;
274 #define SET_RANDOM_COLOR this->setColor(0xff000000 | gRandom.nextU());
275#else
276 #define SET_RANDOM_COLOR
277#endif
278
bsalomon@google.comffca4002011-02-22 20:34:01 +0000279bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000280 const GrIRect* r = NULL;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000281 GrIRect clipRect;
reed@google.comac10a2d2010-12-22 21:39:39 +0000282
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000283 // we check this early because we need a valid
284 // render target to setup stencil clipping
285 // before even going into flushGraphicsState
286 if (NULL == fCurrDrawState.fRenderTarget) {
287 GrAssert(!"No render target bound.");
288 return false;
289 }
290
reed@google.comac10a2d2010-12-22 21:39:39 +0000291 if (fCurrDrawState.fFlagBits & kClip_StateBit) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000292 GrRenderTarget& rt = *fCurrDrawState.fRenderTarget;
293
294 GrRect bounds;
295 GrRect rtRect;
296 rtRect.setLTRB(0, 0,
297 GrIntToScalar(rt.width()), GrIntToScalar(rt.height()));
298 if (fClip.hasBounds()) {
299 bounds = fClip.getBounds();
300 bounds.intersectWith(rtRect);
301 } else {
302 bounds = rtRect;
303 }
304
305 bounds.roundOut(&clipRect);
306 if (clipRect.isEmpty()) {
307 clipRect.setLTRB(0,0,0,0);
308 }
309 r = &clipRect;
310
311 fClipState.fClipInStencil = !fClip.isRect() &&
312 !fClip.isEmpty() &&
313 !bounds.isEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000314
315 if (fClipState.fClipInStencil &&
316 (fClipState.fClipIsDirty ||
bsalomon@google.comd302f142011-03-03 13:54:13 +0000317 fClip != rt.fLastStencilClip)) {
318
319 rt.fLastStencilClip = fClip;
320 // we set the current clip to the bounds so that our recursive
321 // draws are scissored to them. We use the copy of the complex clip
322 // in the rt to render
323 const GrClip& clip = rt.fLastStencilClip;
324 fClip.setFromRect(bounds);
reed@google.comac10a2d2010-12-22 21:39:39 +0000325
326 AutoStateRestore asr(this);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000327 AutoInternalDrawGeomRestore aidgr(this);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000328
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000329 this->setViewMatrix(GrMatrix::I());
bsalomon@google.comd302f142011-03-03 13:54:13 +0000330 this->eraseStencilClip(clipRect);
331 this->flushScissor(NULL);
332#if !VISUALIZE_COMPLEX_CLIP
333 this->enableState(kNoColorWrites_StateBit);
334#else
335 this->disableState(kNoColorWrites_StateBit);
336#endif
337 int count = clip.getElementCount();
338 int clipBit = rt.stencilBits();
339 clipBit = (1 << (clipBit-1));
340
341 // walk through each clip element and perform its set op
342 // with the existing clip.
343 for (int c = 0; c < count; ++c) {
344 GrPathFill fill;
345 // enabled at bottom of loop
346 this->disableState(kModifyStencilClip_StateBit);
347
348 bool canDrawDirectToClip;
349 if (kRect_ClipType == clip.getElementType(c)) {
350 canDrawDirectToClip = true;
351 fill = kEvenOdd_PathFill;
352 } else {
353 fill = clip.getPathFill(c);
354 canDrawDirectToClip = getPathRenderer()->requiresStencilPass(clip.getPath(c));
355 }
356
357 GrSetOp op = 0 == c ? kReplace_SetOp : clip.getOp(c);
358 int passes;
359 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
360
361 canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, canDrawDirectToClip,
362 clipBit, &fill,
363 &passes, stencilSettings);
364
365 // draw the element to the client stencil bits if necessary
366 if (!canDrawDirectToClip) {
367 if (kRect_ClipType == clip.getElementType(c)) {
368 static const GrStencilSettings gDrawToStencil = {
369 kIncClamp_StencilOp, kIncClamp_StencilOp,
370 kIncClamp_StencilOp, kIncClamp_StencilOp,
371 kAlways_StencilFunc, kAlways_StencilFunc,
372 0xffffffff, 0xffffffff,
373 0x00000000, 0x00000000,
374 0xffffffff, 0xffffffff,
375 };
376 this->setStencil(gDrawToStencil);
377 SET_RANDOM_COLOR
378 this->drawSimpleRect(clip.getRect(c), NULL, 0);
379 } else {
380 SET_RANDOM_COLOR
381 getPathRenderer()->drawPathToStencil(this, clip.getPath(c), fill, NULL);
382 }
383 }
384
385 // now we modify the clip bit by rendering either the clip
386 // element directly or a bounding rect of the entire clip.
387 this->enableState(kModifyStencilClip_StateBit);
388 for (int p = 0; p < passes; ++p) {
389 this->setStencil(stencilSettings[p]);
390 if (canDrawDirectToClip) {
391 if (kRect_ClipType == clip.getElementType(c)) {
392 SET_RANDOM_COLOR
393 this->drawSimpleRect(clip.getRect(c), NULL, 0);
394 } else {
395 SET_RANDOM_COLOR
396 getPathRenderer()->drawPath(this, 0, clip.getPath(c), fill, NULL);
397 }
398 } else {
399 SET_RANDOM_COLOR
400 this->drawSimpleRect(bounds, 0, NULL);
401 }
402 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000403 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000404 fClip = clip;
405 // recusive draws would have disabled this.
406 fClipState.fClipInStencil = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000407 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000408
reed@google.comac10a2d2010-12-22 21:39:39 +0000409 fClipState.fClipIsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000410 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000411
reed@google.comac10a2d2010-12-22 21:39:39 +0000412 // Must flush the scissor after graphics state
bsalomon@google.comd302f142011-03-03 13:54:13 +0000413 if (!this->flushGraphicsState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000414 return false;
415 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000416 this->flushScissor(r);
reed@google.comac10a2d2010-12-22 21:39:39 +0000417 return true;
418}
419
bsalomon@google.comd302f142011-03-03 13:54:13 +0000420////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000421
bsalomon@google.comffca4002011-02-22 20:34:01 +0000422void GrGpu::drawIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000423 int startVertex,
424 int startIndex,
425 int vertexCount,
426 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000427 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
428 fReservedGeometry.fLocked);
429 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
430 fReservedGeometry.fLocked);
431
432 if (!setupClipAndFlushState(type)) {
433 return;
434 }
435
436#if GR_COLLECT_STATS
437 fStats.fVertexCnt += vertexCount;
438 fStats.fIndexCnt += indexCount;
439 fStats.fDrawCnt += 1;
440#endif
441
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000442 int sVertex = startVertex;
443 int sIndex = startIndex;
444 setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000445
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000446 drawIndexedHelper(type, sVertex, sIndex,
reed@google.comac10a2d2010-12-22 21:39:39 +0000447 vertexCount, indexCount);
448}
449
bsalomon@google.comffca4002011-02-22 20:34:01 +0000450void GrGpu::drawNonIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000451 int startVertex,
452 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000453 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
454 fReservedGeometry.fLocked);
455
456 if (!setupClipAndFlushState(type)) {
457 return;
458 }
459#if GR_COLLECT_STATS
460 fStats.fVertexCnt += vertexCount;
461 fStats.fDrawCnt += 1;
462#endif
463
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000464 int sVertex = startVertex;
465 setupGeometry(&sVertex, NULL, vertexCount, 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000466
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000467 drawNonIndexedHelper(type, sVertex, vertexCount);
468}
469
470void GrGpu::finalizeReservedVertices() {
471 GrAssert(NULL != fVertexPool);
472 fVertexPool->unlock();
473}
474
475void GrGpu::finalizeReservedIndices() {
476 GrAssert(NULL != fIndexPool);
477 fIndexPool->unlock();
478}
479
480void GrGpu::prepareVertexPool() {
481 if (NULL == fVertexPool) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000482 fVertexPool = new GrVertexBufferAllocPool(this, true,
483 VERTEX_POOL_VB_SIZE,
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +0000484 VERTEX_POOL_VB_COUNT);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000485 } else if (!fVertexPoolInUse) {
486 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000487 fVertexPool->reset();
488 }
489}
490
491void GrGpu::prepareIndexPool() {
492 if (NULL == fVertexPool) {
493 fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000494 } else if (!fIndexPoolInUse) {
495 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000496 fIndexPool->reset();
497 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000498}
499
500bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
501 void** vertices,
502 void** indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000503 GrAssert(!fReservedGeometry.fLocked);
504 size_t reservedVertexSpace = 0;
505
506 if (fReservedGeometry.fVertexCount) {
507 GrAssert(NULL != vertices);
508
bsalomon@google.comd302f142011-03-03 13:54:13 +0000509 this->prepareVertexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000510
511 *vertices = fVertexPool->makeSpace(vertexLayout,
512 fReservedGeometry.fVertexCount,
513 &fCurrPoolVertexBuffer,
514 &fCurrPoolStartVertex);
515 if (NULL == *vertices) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000516 return false;
517 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000518 reservedVertexSpace = VertexSize(vertexLayout) *
519 fReservedGeometry.fVertexCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000520 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000521 if (fReservedGeometry.fIndexCount) {
522 GrAssert(NULL != indices);
523
bsalomon@google.comd302f142011-03-03 13:54:13 +0000524 this->prepareIndexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000525
526 *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
527 &fCurrPoolIndexBuffer,
528 &fCurrPoolStartIndex);
529 if (NULL == *indices) {
530 fVertexPool->putBack(reservedVertexSpace);
531 fCurrPoolVertexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000532 return false;
533 }
534 }
535 return true;
536}
537
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000538void GrGpu::releaseGeometryHelper() {}
539
540void GrGpu::setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount) {
541 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
542 prepareVertexPool();
543#if GR_DEBUG
544 bool success =
545#endif
546 fVertexPool->appendVertices(fGeometrySrc.fVertexLayout,
547 vertexCount,
548 vertexArray,
549 &fCurrPoolVertexBuffer,
550 &fCurrPoolStartVertex);
551 GR_DEBUGASSERT(success);
552}
553
554void GrGpu::setIndexSourceToArrayHelper(const void* indexArray, int indexCount) {
555 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
556 prepareIndexPool();
557#if GR_DEBUG
558 bool success =
559#endif
560 fIndexPool->appendIndices(indexCount,
561 indexArray,
562 &fCurrPoolIndexBuffer,
563 &fCurrPoolStartIndex);
564 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000565}
566
bsalomon@google.comd302f142011-03-03 13:54:13 +0000567////////////////////////////////////////////////////////////////////////////////
568
569GrPathRenderer* GrGpu::getPathRenderer() {
570 if (NULL == fPathRenderer) {
571 fPathRenderer = new GrDefaultPathRenderer(this->supportsTwoSidedStencil(),
572 this->supportsStencilWrapOps());
573 }
574 return fPathRenderer;
575}
576
577////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000578
579const GrGpu::Stats& GrGpu::getStats() const {
580 return fStats;
581}
582
583void GrGpu::resetStats() {
584 memset(&fStats, 0, sizeof(fStats));
585}
586
587void GrGpu::printStats() const {
588 if (GR_COLLECT_STATS) {
589 GrPrintf(
590 "-v-------------------------GPU STATS----------------------------v-\n"
591 "Stats collection is: %s\n"
592 "Draws: %04d, Verts: %04d, Indices: %04d\n"
593 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
594 "TexCreates: %04d, RTCreates:%04d\n"
595 "-^--------------------------------------------------------------^-\n",
596 (GR_COLLECT_STATS ? "ON" : "OFF"),
597 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
598 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
599 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
600 }
601}
602
603////////////////////////////////////////////////////////////////////////////////
604
605GrTexture::~GrTexture() {
606 // use this to set a break-point if needed
607// Gr_clz(3);
608}
609
610const GrSamplerState GrSamplerState::gClampNoFilter(
611 GrSamplerState::kClamp_WrapMode,
612 GrSamplerState::kClamp_WrapMode,
613 GrSamplerState::kNormal_SampleMode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000614 GrMatrix::I(),
reed@google.comac10a2d2010-12-22 21:39:39 +0000615 false);
616
617
618
619