blob: d60287b189b9659367ebbfc1c7bd3561521d61a9 [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
bsalomon@google.com080773c2011-03-15 19:09:25 +000059bool GrTexture::PixelConfigIsAlphaOnly(PixelConfig config) {
60 switch (config) {
61 case GrTexture::kAlpha_8_PixelConfig:
62 return true;
63 default:
64 return false;
65 }
66}
reed@google.comac10a2d2010-12-22 21:39:39 +000067
bsalomon@google.comd302f142011-03-03 13:54:13 +000068////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000069
70extern void gr_run_unittests();
71
72GrGpu::GrGpu() : f8bitPaletteSupport(false),
bsalomon@google.com1c13c962011-02-14 16:51:21 +000073 fCurrPoolVertexBuffer(NULL),
74 fCurrPoolStartVertex(0),
75 fCurrPoolIndexBuffer(NULL),
76 fCurrPoolStartIndex(0),
77 fVertexPool(NULL),
78 fIndexPool(NULL),
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000079 fQuadIndexBuffer(NULL),
bsalomon@google.comd302f142011-03-03 13:54:13 +000080 fUnitSquareVertexBuffer(NULL),
81 fPathRenderer(NULL),
bsalomon@google.coma7f84e12011-03-10 14:13:19 +000082 fContextIsDirty(true),
bsalomon@google.comd302f142011-03-03 13:54:13 +000083 fVertexPoolInUse(false),
84 fIndexPoolInUse(false) {
reed@google.comac10a2d2010-12-22 21:39:39 +000085#if GR_DEBUG
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000086 //gr_run_unittests();
reed@google.comac10a2d2010-12-22 21:39:39 +000087#endif
88 resetStats();
89}
90
91GrGpu::~GrGpu() {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000092 GrSafeUnref(fQuadIndexBuffer);
93 GrSafeUnref(fUnitSquareVertexBuffer);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000094 delete fVertexPool;
95 delete fIndexPool;
bsalomon@google.comd302f142011-03-03 13:54:13 +000096 delete fPathRenderer;
reed@google.comac10a2d2010-12-22 21:39:39 +000097}
98
99void GrGpu::resetContext() {
100}
101
102void GrGpu::unimpl(const char msg[]) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000103#if GR_DEBUG
104 GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
105#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000106}
107
bsalomon@google.comd302f142011-03-03 13:54:13 +0000108////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000109
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000110GrTexture* GrGpu::createTexture(const TextureDesc& desc,
111 const void* srcData, size_t rowBytes) {
112 this->handleDirtyContext();
113 return this->createTextureHelper(desc, srcData, rowBytes);
114}
115
116GrRenderTarget* GrGpu::createPlatformRenderTarget(intptr_t platformRenderTarget,
117 int stencilBits,
118 int width, int height) {
119 this->handleDirtyContext();
120 return this->createPlatformRenderTargetHelper(platformRenderTarget,
121 stencilBits,
122 width, height);
123}
124
125GrRenderTarget* GrGpu::createRenderTargetFrom3DApiState() {
126 this->handleDirtyContext();
127 return this->createRenderTargetFrom3DApiStateHelper();
128}
129
130GrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) {
131 this->handleDirtyContext();
132 return this->createVertexBufferHelper(size, dynamic);
133}
134
135GrIndexBuffer* GrGpu::createIndexBuffer(uint32_t size, bool dynamic) {
136 this->handleDirtyContext();
137 return this->createIndexBufferHelper(size, dynamic);
138}
139
140void GrGpu::eraseColor(GrColor color) {
141 this->handleDirtyContext();
142 this->eraseColorHelper(color);
143}
144
145void GrGpu::forceRenderTargetFlush() {
146 this->handleDirtyContext();
147 this->forceRenderTargetFlushHelper();
148}
149
150bool GrGpu::readPixels(int left, int top, int width, int height,
151 GrTexture::PixelConfig config, void* buffer) {
152 this->handleDirtyContext();
153 return this->readPixelsHelper(left, top, width, height, config, buffer);
154}
155
156////////////////////////////////////////////////////////////////////////////////
157
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000158static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000159
reed@google.com8195f672011-01-12 18:14:28 +0000160GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
reed@google.comac10a2d2010-12-22 21:39:39 +0000161
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000162static inline void fill_indices(uint16_t* indices, int quadCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000163 for (int i = 0; i < quadCount; ++i) {
164 indices[6 * i + 0] = 4 * i + 0;
165 indices[6 * i + 1] = 4 * i + 1;
166 indices[6 * i + 2] = 4 * i + 2;
167 indices[6 * i + 3] = 4 * i + 0;
168 indices[6 * i + 4] = 4 * i + 2;
169 indices[6 * i + 5] = 4 * i + 3;
170 }
171}
172
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000173const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000174 if (NULL == fQuadIndexBuffer) {
175 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
176 GrGpu* me = const_cast<GrGpu*>(this);
177 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
178 if (NULL != fQuadIndexBuffer) {
179 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
180 if (NULL != indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000181 fill_indices(indices, MAX_QUADS);
reed@google.comac10a2d2010-12-22 21:39:39 +0000182 fQuadIndexBuffer->unlock();
183 } else {
184 indices = (uint16_t*)GrMalloc(SIZE);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000185 fill_indices(indices, MAX_QUADS);
reed@google.comac10a2d2010-12-22 21:39:39 +0000186 if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
187 fQuadIndexBuffer->unref();
188 fQuadIndexBuffer = NULL;
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000189 GrCrash("Can't get indices into buffer!");
reed@google.comac10a2d2010-12-22 21:39:39 +0000190 }
191 GrFree(indices);
192 }
193 }
194 }
195
196 return fQuadIndexBuffer;
197}
198
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000199const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000200 if (NULL == fUnitSquareVertexBuffer) {
201
202 static const GrPoint DATA[] = {
203 GrPoint(0, 0),
204 GrPoint(GR_Scalar1,0),
205 GrPoint(GR_Scalar1,GR_Scalar1),
206 GrPoint(0, GR_Scalar1)
207 };
208 static const size_t SIZE = sizeof(DATA);
209
210 GrGpu* me = const_cast<GrGpu*>(this);
211 fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false);
212 if (NULL != fUnitSquareVertexBuffer) {
213 if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) {
214 fUnitSquareVertexBuffer->unref();
215 fUnitSquareVertexBuffer = NULL;
216 GrCrash("Can't get vertices into buffer!");
217 }
218 }
219 }
220
221 return fUnitSquareVertexBuffer;
222}
223
bsalomon@google.comd302f142011-03-03 13:54:13 +0000224////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000225
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000226void GrGpu::clipWillBeSet(const GrClip& newClip) {
227 if (newClip != fClip) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000228 fClipState.fClipIsDirty = true;
229 }
230}
231
bsalomon@google.comd302f142011-03-03 13:54:13 +0000232////////////////////////////////////////////////////////////////////////////////
233
234// stencil settings to use when clip is in stencil
235const GrStencilSettings GrGpu::gClipStencilSettings = {
236 kKeep_StencilOp, kKeep_StencilOp,
237 kKeep_StencilOp, kKeep_StencilOp,
238 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
239 0, 0,
240 0, 0,
241 0, 0
242};
243
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000244// mapping of clip-respecting stencil funcs to normal stencil funcs
245// mapping depends on whether stencil-clipping is in effect.
bsalomon@google.comd302f142011-03-03 13:54:13 +0000246static const GrStencilFunc gGrClipToNormalStencilFunc[2][kClipStencilFuncCount] = {
247 {// Stencil-Clipping is DISABLED, effectively always inside the clip
248 // In the Clip Funcs
249 kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc
250 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc
251 kLess_StencilFunc, // kLessIfInClip_StencilFunc
252 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc
253 // Special in the clip func that forces user's ref to be 0.
254 kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc
255 // make ref 0 and do normal nequal.
256 },
257 {// Stencil-Clipping is ENABLED
258 // In the Clip Funcs
259 kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc
260 // eq stencil clip bit, mask
261 // out user bits.
262
263 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc
264 // add stencil bit to mask and ref
265
266 kLess_StencilFunc, // kLessIfInClip_StencilFunc
267 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc
268 // for both of these we can add
269 // the clip bit to the mask and
270 // ref and compare as normal
271 // Special in the clip func that forces user's ref to be 0.
272 kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc
273 // make ref have only the clip bit set
274 // and make comparison be less
275 // 10..0 < 1..user_bits..
276 }
277};
278
279GrStencilFunc GrGpu::ConvertStencilFunc(bool stencilInClip, GrStencilFunc func) {
280 GrAssert(func >= 0);
281 if (func >= kBasicStencilFuncCount) {
282 GrAssert(func < kStencilFuncCount);
283 func = gGrClipToNormalStencilFunc[stencilInClip ? 1 : 0][func - kBasicStencilFuncCount];
284 GrAssert(func >= 0 && func < kBasicStencilFuncCount);
285 }
286 return func;
287}
288
289void GrGpu::ConvertStencilFuncAndMask(GrStencilFunc func,
290 bool clipInStencil,
291 unsigned int clipBit,
292 unsigned int userBits,
293 unsigned int* ref,
294 unsigned int* mask) {
295 if (func < kBasicStencilFuncCount) {
296 *mask &= userBits;
297 *ref &= userBits;
298 } else {
299 if (clipInStencil) {
300 switch (func) {
301 case kAlwaysIfInClip_StencilFunc:
302 *mask = clipBit;
303 *ref = clipBit;
304 break;
305 case kEqualIfInClip_StencilFunc:
306 case kLessIfInClip_StencilFunc:
307 case kLEqualIfInClip_StencilFunc:
308 *mask = (*mask & userBits) | clipBit;
309 *ref = (*ref & userBits) | clipBit;
310 break;
311 case kNonZeroIfInClip_StencilFunc:
312 *mask = (*mask & userBits) | clipBit;
313 *ref = clipBit;
314 break;
315 default:
316 GrCrash("Unknown stencil func");
317 }
318 } else {
319 *mask &= userBits;
320 *ref &= userBits;
321 }
322 }
323}
324
325////////////////////////////////////////////////////////////////////////////////
326
327#define VISUALIZE_COMPLEX_CLIP 0
328
329#if VISUALIZE_COMPLEX_CLIP
330 #include "GrRandom.h"
331 GrRandom gRandom;
332 #define SET_RANDOM_COLOR this->setColor(0xff000000 | gRandom.nextU());
333#else
334 #define SET_RANDOM_COLOR
335#endif
336
bsalomon@google.comffca4002011-02-22 20:34:01 +0000337bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000338 const GrIRect* r = NULL;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000339 GrIRect clipRect;
reed@google.comac10a2d2010-12-22 21:39:39 +0000340
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000341 // we check this early because we need a valid
342 // render target to setup stencil clipping
343 // before even going into flushGraphicsState
344 if (NULL == fCurrDrawState.fRenderTarget) {
345 GrAssert(!"No render target bound.");
346 return false;
347 }
348
reed@google.comac10a2d2010-12-22 21:39:39 +0000349 if (fCurrDrawState.fFlagBits & kClip_StateBit) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000350 GrRenderTarget& rt = *fCurrDrawState.fRenderTarget;
351
352 GrRect bounds;
353 GrRect rtRect;
354 rtRect.setLTRB(0, 0,
355 GrIntToScalar(rt.width()), GrIntToScalar(rt.height()));
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000356 if (fClip.hasConservativeBounds()) {
357 bounds = fClip.getConservativeBounds();
bsalomon@google.comd302f142011-03-03 13:54:13 +0000358 bounds.intersectWith(rtRect);
359 } else {
360 bounds = rtRect;
361 }
362
363 bounds.roundOut(&clipRect);
364 if (clipRect.isEmpty()) {
365 clipRect.setLTRB(0,0,0,0);
366 }
367 r = &clipRect;
368
369 fClipState.fClipInStencil = !fClip.isRect() &&
370 !fClip.isEmpty() &&
371 !bounds.isEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000372
373 if (fClipState.fClipInStencil &&
374 (fClipState.fClipIsDirty ||
bsalomon@google.comd302f142011-03-03 13:54:13 +0000375 fClip != rt.fLastStencilClip)) {
376
377 rt.fLastStencilClip = fClip;
378 // we set the current clip to the bounds so that our recursive
379 // draws are scissored to them. We use the copy of the complex clip
380 // in the rt to render
381 const GrClip& clip = rt.fLastStencilClip;
382 fClip.setFromRect(bounds);
reed@google.comac10a2d2010-12-22 21:39:39 +0000383
384 AutoStateRestore asr(this);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000385 AutoInternalDrawGeomRestore aidgr(this);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000386
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000387 this->setViewMatrix(GrMatrix::I());
bsalomon@google.comd302f142011-03-03 13:54:13 +0000388 this->eraseStencilClip(clipRect);
389 this->flushScissor(NULL);
390#if !VISUALIZE_COMPLEX_CLIP
391 this->enableState(kNoColorWrites_StateBit);
392#else
393 this->disableState(kNoColorWrites_StateBit);
394#endif
395 int count = clip.getElementCount();
396 int clipBit = rt.stencilBits();
397 clipBit = (1 << (clipBit-1));
398
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000399 // often we'll see the first two elements of the clip are
400 // the full rt size and another element intersected with it.
401 // We can skip the first full-size rect and save a big rect draw.
402 int firstElement = 0;
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000403 if (clip.getElementCount() > 1 &&
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000404 kRect_ClipType == clip.getElementType(0) &&
405 kIntersect_SetOp == clip.getOp(1)&&
406 clip.getRect(0).contains(bounds)) {
407 firstElement = 1;
408 }
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000409
bsalomon@google.comd302f142011-03-03 13:54:13 +0000410 // walk through each clip element and perform its set op
411 // with the existing clip.
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000412 for (int c = firstElement; c < count; ++c) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000413 GrPathFill fill;
414 // enabled at bottom of loop
415 this->disableState(kModifyStencilClip_StateBit);
416
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000417 bool canRenderDirectToStencil; // can the clip element be drawn
418 // directly to the stencil buffer
419 // with a non-inverted fill rule
420 // without extra passes to
421 // resolve in/out status.
bsalomon@google.comd302f142011-03-03 13:54:13 +0000422 if (kRect_ClipType == clip.getElementType(c)) {
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000423 canRenderDirectToStencil = true;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000424 fill = kEvenOdd_PathFill;
425 } else {
426 fill = clip.getPathFill(c);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000427 GrPathRenderer* pr = this->getPathRenderer();
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000428 canRenderDirectToStencil =
429 !pr->requiresStencilPass(this, clip.getPath(c),
430 NonInvertedFill(fill));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000431 }
432
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000433 GrSetOp op = firstElement == c ? kReplace_SetOp : clip.getOp(c);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000434 int passes;
435 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
436
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000437 bool canDrawDirectToClip; // Given the renderer, the element,
438 // fill rule, and set operation can
439 // we render the element directly to
440 // stencil bit used for clipping.
441 canDrawDirectToClip =
442 GrStencilSettings::GetClipPasses(op,
443 canRenderDirectToStencil,
444 clipBit,
445 IsFillInverted(fill),
446 &passes, stencilSettings);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000447
448 // draw the element to the client stencil bits if necessary
449 if (!canDrawDirectToClip) {
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000450 static const GrStencilSettings gDrawToStencil = {
451 kIncClamp_StencilOp, kIncClamp_StencilOp,
452 kIncClamp_StencilOp, kIncClamp_StencilOp,
453 kAlways_StencilFunc, kAlways_StencilFunc,
454 0xffffffff, 0xffffffff,
455 0x00000000, 0x00000000,
456 0xffffffff, 0xffffffff,
457 };
458 SET_RANDOM_COLOR
bsalomon@google.comd302f142011-03-03 13:54:13 +0000459 if (kRect_ClipType == clip.getElementType(c)) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000460 this->setStencil(gDrawToStencil);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000461 this->drawSimpleRect(clip.getRect(c), NULL, 0);
462 } else {
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000463 if (canRenderDirectToStencil) {
464 this->setStencil(gDrawToStencil);
465 getPathRenderer()->drawPath(this, 0,
466 clip.getPath(c),
467 NonInvertedFill(fill),
468 NULL);
469 } else {
470 getPathRenderer()->drawPathToStencil(this, clip.getPath(c),
471 NonInvertedFill(fill),
472 NULL);
473 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000474 }
475 }
476
477 // now we modify the clip bit by rendering either the clip
478 // element directly or a bounding rect of the entire clip.
479 this->enableState(kModifyStencilClip_StateBit);
480 for (int p = 0; p < passes; ++p) {
481 this->setStencil(stencilSettings[p]);
482 if (canDrawDirectToClip) {
483 if (kRect_ClipType == clip.getElementType(c)) {
484 SET_RANDOM_COLOR
485 this->drawSimpleRect(clip.getRect(c), NULL, 0);
486 } else {
487 SET_RANDOM_COLOR
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000488 GrAssert(!IsFillInverted(fill));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000489 getPathRenderer()->drawPath(this, 0,
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000490 clip.getPath(c),
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000491 fill, NULL);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000492 }
493 } else {
494 SET_RANDOM_COLOR
495 this->drawSimpleRect(bounds, 0, NULL);
496 }
497 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000498 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000499 fClip = clip;
500 // recusive draws would have disabled this.
501 fClipState.fClipInStencil = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000502 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000503
reed@google.comac10a2d2010-12-22 21:39:39 +0000504 fClipState.fClipIsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000505 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000506
reed@google.comac10a2d2010-12-22 21:39:39 +0000507 // Must flush the scissor after graphics state
bsalomon@google.comd302f142011-03-03 13:54:13 +0000508 if (!this->flushGraphicsState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000509 return false;
510 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000511 this->flushScissor(r);
reed@google.comac10a2d2010-12-22 21:39:39 +0000512 return true;
513}
514
bsalomon@google.comd302f142011-03-03 13:54:13 +0000515////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000516
bsalomon@google.comffca4002011-02-22 20:34:01 +0000517void GrGpu::drawIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000518 int startVertex,
519 int startIndex,
520 int vertexCount,
521 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000522 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
523 fReservedGeometry.fLocked);
524 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
525 fReservedGeometry.fLocked);
526
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000527 this->handleDirtyContext();
528
529 if (!this->setupClipAndFlushState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000530 return;
531 }
532
533#if GR_COLLECT_STATS
534 fStats.fVertexCnt += vertexCount;
535 fStats.fIndexCnt += indexCount;
536 fStats.fDrawCnt += 1;
537#endif
538
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000539 int sVertex = startVertex;
540 int sIndex = startIndex;
541 setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000542
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000543 drawIndexedHelper(type, sVertex, sIndex,
reed@google.comac10a2d2010-12-22 21:39:39 +0000544 vertexCount, indexCount);
545}
546
bsalomon@google.comffca4002011-02-22 20:34:01 +0000547void GrGpu::drawNonIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000548 int startVertex,
549 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000550 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
551 fReservedGeometry.fLocked);
552
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000553 this->handleDirtyContext();
554
555 if (!this->setupClipAndFlushState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000556 return;
557 }
558#if GR_COLLECT_STATS
559 fStats.fVertexCnt += vertexCount;
560 fStats.fDrawCnt += 1;
561#endif
562
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000563 int sVertex = startVertex;
564 setupGeometry(&sVertex, NULL, vertexCount, 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000565
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000566 drawNonIndexedHelper(type, sVertex, vertexCount);
567}
568
569void GrGpu::finalizeReservedVertices() {
570 GrAssert(NULL != fVertexPool);
571 fVertexPool->unlock();
572}
573
574void GrGpu::finalizeReservedIndices() {
575 GrAssert(NULL != fIndexPool);
576 fIndexPool->unlock();
577}
578
579void GrGpu::prepareVertexPool() {
580 if (NULL == fVertexPool) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000581 fVertexPool = new GrVertexBufferAllocPool(this, true,
582 VERTEX_POOL_VB_SIZE,
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +0000583 VERTEX_POOL_VB_COUNT);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000584 } else if (!fVertexPoolInUse) {
585 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000586 fVertexPool->reset();
587 }
588}
589
590void GrGpu::prepareIndexPool() {
591 if (NULL == fVertexPool) {
592 fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000593 } else if (!fIndexPoolInUse) {
594 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000595 fIndexPool->reset();
596 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000597}
598
599bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
600 void** vertices,
601 void** indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000602 GrAssert(!fReservedGeometry.fLocked);
603 size_t reservedVertexSpace = 0;
604
605 if (fReservedGeometry.fVertexCount) {
606 GrAssert(NULL != vertices);
607
bsalomon@google.comd302f142011-03-03 13:54:13 +0000608 this->prepareVertexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000609
610 *vertices = fVertexPool->makeSpace(vertexLayout,
611 fReservedGeometry.fVertexCount,
612 &fCurrPoolVertexBuffer,
613 &fCurrPoolStartVertex);
614 if (NULL == *vertices) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000615 return false;
616 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000617 reservedVertexSpace = VertexSize(vertexLayout) *
618 fReservedGeometry.fVertexCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000619 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000620 if (fReservedGeometry.fIndexCount) {
621 GrAssert(NULL != indices);
622
bsalomon@google.comd302f142011-03-03 13:54:13 +0000623 this->prepareIndexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000624
625 *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
626 &fCurrPoolIndexBuffer,
627 &fCurrPoolStartIndex);
628 if (NULL == *indices) {
629 fVertexPool->putBack(reservedVertexSpace);
630 fCurrPoolVertexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000631 return false;
632 }
633 }
634 return true;
635}
636
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000637void GrGpu::releaseGeometryHelper() {}
638
639void GrGpu::setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount) {
640 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
641 prepareVertexPool();
642#if GR_DEBUG
643 bool success =
644#endif
645 fVertexPool->appendVertices(fGeometrySrc.fVertexLayout,
646 vertexCount,
647 vertexArray,
648 &fCurrPoolVertexBuffer,
649 &fCurrPoolStartVertex);
650 GR_DEBUGASSERT(success);
651}
652
653void GrGpu::setIndexSourceToArrayHelper(const void* indexArray, int indexCount) {
654 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
655 prepareIndexPool();
656#if GR_DEBUG
657 bool success =
658#endif
659 fIndexPool->appendIndices(indexCount,
660 indexArray,
661 &fCurrPoolIndexBuffer,
662 &fCurrPoolStartIndex);
663 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000664}
665
bsalomon@google.comd302f142011-03-03 13:54:13 +0000666////////////////////////////////////////////////////////////////////////////////
667
668GrPathRenderer* GrGpu::getPathRenderer() {
669 if (NULL == fPathRenderer) {
670 fPathRenderer = new GrDefaultPathRenderer(this->supportsTwoSidedStencil(),
671 this->supportsStencilWrapOps());
672 }
673 return fPathRenderer;
674}
675
676////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000677
678const GrGpu::Stats& GrGpu::getStats() const {
679 return fStats;
680}
681
682void GrGpu::resetStats() {
683 memset(&fStats, 0, sizeof(fStats));
684}
685
686void GrGpu::printStats() const {
687 if (GR_COLLECT_STATS) {
688 GrPrintf(
689 "-v-------------------------GPU STATS----------------------------v-\n"
690 "Stats collection is: %s\n"
691 "Draws: %04d, Verts: %04d, Indices: %04d\n"
692 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
693 "TexCreates: %04d, RTCreates:%04d\n"
694 "-^--------------------------------------------------------------^-\n",
695 (GR_COLLECT_STATS ? "ON" : "OFF"),
696 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
697 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
698 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
699 }
700}
701
702////////////////////////////////////////////////////////////////////////////////
703
704GrTexture::~GrTexture() {
705 // use this to set a break-point if needed
706// Gr_clz(3);
707}
708
709const GrSamplerState GrSamplerState::gClampNoFilter(
710 GrSamplerState::kClamp_WrapMode,
711 GrSamplerState::kClamp_WrapMode,
712 GrSamplerState::kNormal_SampleMode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000713 GrMatrix::I(),
reed@google.comac10a2d2010-12-22 21:39:39 +0000714 false);
715
716
717
718