blob: 045dcd00b6ff0a6140fea5e5e559a26dd060957f [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
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000077 //gr_run_unittests();
reed@google.comac10a2d2010-12-22 21:39:39 +000078#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()));
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000298 if (fClip.hasConservativeBounds()) {
299 bounds = fClip.getConservativeBounds();
bsalomon@google.comd302f142011-03-03 13:54:13 +0000300 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
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000341 // often we'll see the first two elements of the clip are
342 // the full rt size and another element intersected with it.
343 // We can skip the first full-size rect and save a big rect draw.
344 int firstElement = 0;
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000345 if (clip.getElementCount() > 1 &&
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000346 kRect_ClipType == clip.getElementType(0) &&
347 kIntersect_SetOp == clip.getOp(1)&&
348 clip.getRect(0).contains(bounds)) {
349 firstElement = 1;
350 }
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000351
bsalomon@google.comd302f142011-03-03 13:54:13 +0000352 // walk through each clip element and perform its set op
353 // with the existing clip.
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000354 for (int c = firstElement; c < count; ++c) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000355 GrPathFill fill;
356 // enabled at bottom of loop
357 this->disableState(kModifyStencilClip_StateBit);
358
359 bool canDrawDirectToClip;
360 if (kRect_ClipType == clip.getElementType(c)) {
361 canDrawDirectToClip = true;
362 fill = kEvenOdd_PathFill;
363 } else {
364 fill = clip.getPathFill(c);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000365 GrPathRenderer* pr = this->getPathRenderer();
366 canDrawDirectToClip = pr->requiresStencilPass(this, clip.getPath(c), fill);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000367 }
368
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000369 GrSetOp op = firstElement == c ? kReplace_SetOp : clip.getOp(c);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000370 int passes;
371 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
372
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000373 canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, canDrawDirectToClip,
374 clipBit, IsFillInverted(fill),
bsalomon@google.comd302f142011-03-03 13:54:13 +0000375 &passes, stencilSettings);
376
377 // draw the element to the client stencil bits if necessary
378 if (!canDrawDirectToClip) {
379 if (kRect_ClipType == clip.getElementType(c)) {
380 static const GrStencilSettings gDrawToStencil = {
381 kIncClamp_StencilOp, kIncClamp_StencilOp,
382 kIncClamp_StencilOp, kIncClamp_StencilOp,
383 kAlways_StencilFunc, kAlways_StencilFunc,
384 0xffffffff, 0xffffffff,
385 0x00000000, 0x00000000,
386 0xffffffff, 0xffffffff,
387 };
388 this->setStencil(gDrawToStencil);
389 SET_RANDOM_COLOR
390 this->drawSimpleRect(clip.getRect(c), NULL, 0);
391 } else {
392 SET_RANDOM_COLOR
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000393 getPathRenderer()->drawPathToStencil(this, clip.getPath(c),
394 NonInvertedFill(fill),
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000395 NULL);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000396 }
397 }
398
399 // now we modify the clip bit by rendering either the clip
400 // element directly or a bounding rect of the entire clip.
401 this->enableState(kModifyStencilClip_StateBit);
402 for (int p = 0; p < passes; ++p) {
403 this->setStencil(stencilSettings[p]);
404 if (canDrawDirectToClip) {
405 if (kRect_ClipType == clip.getElementType(c)) {
406 SET_RANDOM_COLOR
407 this->drawSimpleRect(clip.getRect(c), NULL, 0);
408 } else {
409 SET_RANDOM_COLOR
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000410 getPathRenderer()->drawPath(this, 0,
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000411 clip.getPath(c),
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000412 fill, NULL);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000413 }
414 } else {
415 SET_RANDOM_COLOR
416 this->drawSimpleRect(bounds, 0, NULL);
417 }
418 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000419 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000420 fClip = clip;
421 // recusive draws would have disabled this.
422 fClipState.fClipInStencil = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000423 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000424
reed@google.comac10a2d2010-12-22 21:39:39 +0000425 fClipState.fClipIsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000426 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000427
reed@google.comac10a2d2010-12-22 21:39:39 +0000428 // Must flush the scissor after graphics state
bsalomon@google.comd302f142011-03-03 13:54:13 +0000429 if (!this->flushGraphicsState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000430 return false;
431 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000432 this->flushScissor(r);
reed@google.comac10a2d2010-12-22 21:39:39 +0000433 return true;
434}
435
bsalomon@google.comd302f142011-03-03 13:54:13 +0000436////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000437
bsalomon@google.comffca4002011-02-22 20:34:01 +0000438void GrGpu::drawIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000439 int startVertex,
440 int startIndex,
441 int vertexCount,
442 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000443 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
444 fReservedGeometry.fLocked);
445 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
446 fReservedGeometry.fLocked);
447
448 if (!setupClipAndFlushState(type)) {
449 return;
450 }
451
452#if GR_COLLECT_STATS
453 fStats.fVertexCnt += vertexCount;
454 fStats.fIndexCnt += indexCount;
455 fStats.fDrawCnt += 1;
456#endif
457
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000458 int sVertex = startVertex;
459 int sIndex = startIndex;
460 setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000461
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000462 drawIndexedHelper(type, sVertex, sIndex,
reed@google.comac10a2d2010-12-22 21:39:39 +0000463 vertexCount, indexCount);
464}
465
bsalomon@google.comffca4002011-02-22 20:34:01 +0000466void GrGpu::drawNonIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000467 int startVertex,
468 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000469 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
470 fReservedGeometry.fLocked);
471
472 if (!setupClipAndFlushState(type)) {
473 return;
474 }
475#if GR_COLLECT_STATS
476 fStats.fVertexCnt += vertexCount;
477 fStats.fDrawCnt += 1;
478#endif
479
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000480 int sVertex = startVertex;
481 setupGeometry(&sVertex, NULL, vertexCount, 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000482
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000483 drawNonIndexedHelper(type, sVertex, vertexCount);
484}
485
486void GrGpu::finalizeReservedVertices() {
487 GrAssert(NULL != fVertexPool);
488 fVertexPool->unlock();
489}
490
491void GrGpu::finalizeReservedIndices() {
492 GrAssert(NULL != fIndexPool);
493 fIndexPool->unlock();
494}
495
496void GrGpu::prepareVertexPool() {
497 if (NULL == fVertexPool) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000498 fVertexPool = new GrVertexBufferAllocPool(this, true,
499 VERTEX_POOL_VB_SIZE,
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +0000500 VERTEX_POOL_VB_COUNT);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000501 } else if (!fVertexPoolInUse) {
502 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000503 fVertexPool->reset();
504 }
505}
506
507void GrGpu::prepareIndexPool() {
508 if (NULL == fVertexPool) {
509 fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000510 } else if (!fIndexPoolInUse) {
511 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000512 fIndexPool->reset();
513 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000514}
515
516bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
517 void** vertices,
518 void** indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000519 GrAssert(!fReservedGeometry.fLocked);
520 size_t reservedVertexSpace = 0;
521
522 if (fReservedGeometry.fVertexCount) {
523 GrAssert(NULL != vertices);
524
bsalomon@google.comd302f142011-03-03 13:54:13 +0000525 this->prepareVertexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000526
527 *vertices = fVertexPool->makeSpace(vertexLayout,
528 fReservedGeometry.fVertexCount,
529 &fCurrPoolVertexBuffer,
530 &fCurrPoolStartVertex);
531 if (NULL == *vertices) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000532 return false;
533 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000534 reservedVertexSpace = VertexSize(vertexLayout) *
535 fReservedGeometry.fVertexCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000536 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000537 if (fReservedGeometry.fIndexCount) {
538 GrAssert(NULL != indices);
539
bsalomon@google.comd302f142011-03-03 13:54:13 +0000540 this->prepareIndexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000541
542 *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
543 &fCurrPoolIndexBuffer,
544 &fCurrPoolStartIndex);
545 if (NULL == *indices) {
546 fVertexPool->putBack(reservedVertexSpace);
547 fCurrPoolVertexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000548 return false;
549 }
550 }
551 return true;
552}
553
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000554void GrGpu::releaseGeometryHelper() {}
555
556void GrGpu::setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount) {
557 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
558 prepareVertexPool();
559#if GR_DEBUG
560 bool success =
561#endif
562 fVertexPool->appendVertices(fGeometrySrc.fVertexLayout,
563 vertexCount,
564 vertexArray,
565 &fCurrPoolVertexBuffer,
566 &fCurrPoolStartVertex);
567 GR_DEBUGASSERT(success);
568}
569
570void GrGpu::setIndexSourceToArrayHelper(const void* indexArray, int indexCount) {
571 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
572 prepareIndexPool();
573#if GR_DEBUG
574 bool success =
575#endif
576 fIndexPool->appendIndices(indexCount,
577 indexArray,
578 &fCurrPoolIndexBuffer,
579 &fCurrPoolStartIndex);
580 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000581}
582
bsalomon@google.comd302f142011-03-03 13:54:13 +0000583////////////////////////////////////////////////////////////////////////////////
584
585GrPathRenderer* GrGpu::getPathRenderer() {
586 if (NULL == fPathRenderer) {
587 fPathRenderer = new GrDefaultPathRenderer(this->supportsTwoSidedStencil(),
588 this->supportsStencilWrapOps());
589 }
590 return fPathRenderer;
591}
592
593////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000594
595const GrGpu::Stats& GrGpu::getStats() const {
596 return fStats;
597}
598
599void GrGpu::resetStats() {
600 memset(&fStats, 0, sizeof(fStats));
601}
602
603void GrGpu::printStats() const {
604 if (GR_COLLECT_STATS) {
605 GrPrintf(
606 "-v-------------------------GPU STATS----------------------------v-\n"
607 "Stats collection is: %s\n"
608 "Draws: %04d, Verts: %04d, Indices: %04d\n"
609 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
610 "TexCreates: %04d, RTCreates:%04d\n"
611 "-^--------------------------------------------------------------^-\n",
612 (GR_COLLECT_STATS ? "ON" : "OFF"),
613 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
614 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
615 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
616 }
617}
618
619////////////////////////////////////////////////////////////////////////////////
620
621GrTexture::~GrTexture() {
622 // use this to set a break-point if needed
623// Gr_clz(3);
624}
625
626const GrSamplerState GrSamplerState::gClampNoFilter(
627 GrSamplerState::kClamp_WrapMode,
628 GrSamplerState::kClamp_WrapMode,
629 GrSamplerState::kNormal_SampleMode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000630 GrMatrix::I(),
reed@google.comac10a2d2010-12-22 21:39:39 +0000631 false);
632
633
634
635