blob: d41005b531991d0a4f6aac2a6307d107696c15d7 [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),
bsalomon@google.coma7f84e12011-03-10 14:13:19 +000074 fContextIsDirty(true),
bsalomon@google.comd302f142011-03-03 13:54:13 +000075 fVertexPoolInUse(false),
76 fIndexPoolInUse(false) {
reed@google.comac10a2d2010-12-22 21:39:39 +000077#if GR_DEBUG
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000078 //gr_run_unittests();
reed@google.comac10a2d2010-12-22 21:39:39 +000079#endif
80 resetStats();
81}
82
83GrGpu::~GrGpu() {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000084 GrSafeUnref(fQuadIndexBuffer);
85 GrSafeUnref(fUnitSquareVertexBuffer);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000086 delete fVertexPool;
87 delete fIndexPool;
bsalomon@google.comd302f142011-03-03 13:54:13 +000088 delete fPathRenderer;
reed@google.comac10a2d2010-12-22 21:39:39 +000089}
90
91void GrGpu::resetContext() {
92}
93
94void GrGpu::unimpl(const char msg[]) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +000095#if GR_DEBUG
96 GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
97#endif
reed@google.comac10a2d2010-12-22 21:39:39 +000098}
99
bsalomon@google.comd302f142011-03-03 13:54:13 +0000100////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000101
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000102GrTexture* GrGpu::createTexture(const TextureDesc& desc,
103 const void* srcData, size_t rowBytes) {
104 this->handleDirtyContext();
105 return this->createTextureHelper(desc, srcData, rowBytes);
106}
107
108GrRenderTarget* GrGpu::createPlatformRenderTarget(intptr_t platformRenderTarget,
109 int stencilBits,
110 int width, int height) {
111 this->handleDirtyContext();
112 return this->createPlatformRenderTargetHelper(platformRenderTarget,
113 stencilBits,
114 width, height);
115}
116
117GrRenderTarget* GrGpu::createRenderTargetFrom3DApiState() {
118 this->handleDirtyContext();
119 return this->createRenderTargetFrom3DApiStateHelper();
120}
121
122GrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) {
123 this->handleDirtyContext();
124 return this->createVertexBufferHelper(size, dynamic);
125}
126
127GrIndexBuffer* GrGpu::createIndexBuffer(uint32_t size, bool dynamic) {
128 this->handleDirtyContext();
129 return this->createIndexBufferHelper(size, dynamic);
130}
131
132void GrGpu::eraseColor(GrColor color) {
133 this->handleDirtyContext();
134 this->eraseColorHelper(color);
135}
136
137void GrGpu::forceRenderTargetFlush() {
138 this->handleDirtyContext();
139 this->forceRenderTargetFlushHelper();
140}
141
142bool GrGpu::readPixels(int left, int top, int width, int height,
143 GrTexture::PixelConfig config, void* buffer) {
144 this->handleDirtyContext();
145 return this->readPixelsHelper(left, top, width, height, config, buffer);
146}
147
148////////////////////////////////////////////////////////////////////////////////
149
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000150static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000151
reed@google.com8195f672011-01-12 18:14:28 +0000152GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
reed@google.comac10a2d2010-12-22 21:39:39 +0000153
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000154static inline void fill_indices(uint16_t* indices, int quadCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000155 for (int i = 0; i < quadCount; ++i) {
156 indices[6 * i + 0] = 4 * i + 0;
157 indices[6 * i + 1] = 4 * i + 1;
158 indices[6 * i + 2] = 4 * i + 2;
159 indices[6 * i + 3] = 4 * i + 0;
160 indices[6 * i + 4] = 4 * i + 2;
161 indices[6 * i + 5] = 4 * i + 3;
162 }
163}
164
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000165const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000166 if (NULL == fQuadIndexBuffer) {
167 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
168 GrGpu* me = const_cast<GrGpu*>(this);
169 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
170 if (NULL != fQuadIndexBuffer) {
171 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
172 if (NULL != indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000173 fill_indices(indices, MAX_QUADS);
reed@google.comac10a2d2010-12-22 21:39:39 +0000174 fQuadIndexBuffer->unlock();
175 } else {
176 indices = (uint16_t*)GrMalloc(SIZE);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000177 fill_indices(indices, MAX_QUADS);
reed@google.comac10a2d2010-12-22 21:39:39 +0000178 if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
179 fQuadIndexBuffer->unref();
180 fQuadIndexBuffer = NULL;
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000181 GrCrash("Can't get indices into buffer!");
reed@google.comac10a2d2010-12-22 21:39:39 +0000182 }
183 GrFree(indices);
184 }
185 }
186 }
187
188 return fQuadIndexBuffer;
189}
190
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000191const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000192 if (NULL == fUnitSquareVertexBuffer) {
193
194 static const GrPoint DATA[] = {
195 GrPoint(0, 0),
196 GrPoint(GR_Scalar1,0),
197 GrPoint(GR_Scalar1,GR_Scalar1),
198 GrPoint(0, GR_Scalar1)
199 };
200 static const size_t SIZE = sizeof(DATA);
201
202 GrGpu* me = const_cast<GrGpu*>(this);
203 fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false);
204 if (NULL != fUnitSquareVertexBuffer) {
205 if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) {
206 fUnitSquareVertexBuffer->unref();
207 fUnitSquareVertexBuffer = NULL;
208 GrCrash("Can't get vertices into buffer!");
209 }
210 }
211 }
212
213 return fUnitSquareVertexBuffer;
214}
215
bsalomon@google.comd302f142011-03-03 13:54:13 +0000216////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000217
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000218void GrGpu::clipWillBeSet(const GrClip& newClip) {
219 if (newClip != fClip) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000220 fClipState.fClipIsDirty = true;
221 }
222}
223
bsalomon@google.comd302f142011-03-03 13:54:13 +0000224////////////////////////////////////////////////////////////////////////////////
225
226// stencil settings to use when clip is in stencil
227const GrStencilSettings GrGpu::gClipStencilSettings = {
228 kKeep_StencilOp, kKeep_StencilOp,
229 kKeep_StencilOp, kKeep_StencilOp,
230 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
231 0, 0,
232 0, 0,
233 0, 0
234};
235
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000236// mapping of clip-respecting stencil funcs to normal stencil funcs
237// mapping depends on whether stencil-clipping is in effect.
bsalomon@google.comd302f142011-03-03 13:54:13 +0000238static const GrStencilFunc gGrClipToNormalStencilFunc[2][kClipStencilFuncCount] = {
239 {// Stencil-Clipping is DISABLED, effectively always inside the clip
240 // In the Clip Funcs
241 kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc
242 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc
243 kLess_StencilFunc, // kLessIfInClip_StencilFunc
244 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc
245 // Special in the clip func that forces user's ref to be 0.
246 kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc
247 // make ref 0 and do normal nequal.
248 },
249 {// Stencil-Clipping is ENABLED
250 // In the Clip Funcs
251 kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc
252 // eq stencil clip bit, mask
253 // out user bits.
254
255 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc
256 // add stencil bit to mask and ref
257
258 kLess_StencilFunc, // kLessIfInClip_StencilFunc
259 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc
260 // for both of these we can add
261 // the clip bit to the mask and
262 // ref and compare as normal
263 // Special in the clip func that forces user's ref to be 0.
264 kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc
265 // make ref have only the clip bit set
266 // and make comparison be less
267 // 10..0 < 1..user_bits..
268 }
269};
270
271GrStencilFunc GrGpu::ConvertStencilFunc(bool stencilInClip, GrStencilFunc func) {
272 GrAssert(func >= 0);
273 if (func >= kBasicStencilFuncCount) {
274 GrAssert(func < kStencilFuncCount);
275 func = gGrClipToNormalStencilFunc[stencilInClip ? 1 : 0][func - kBasicStencilFuncCount];
276 GrAssert(func >= 0 && func < kBasicStencilFuncCount);
277 }
278 return func;
279}
280
281void GrGpu::ConvertStencilFuncAndMask(GrStencilFunc func,
282 bool clipInStencil,
283 unsigned int clipBit,
284 unsigned int userBits,
285 unsigned int* ref,
286 unsigned int* mask) {
287 if (func < kBasicStencilFuncCount) {
288 *mask &= userBits;
289 *ref &= userBits;
290 } else {
291 if (clipInStencil) {
292 switch (func) {
293 case kAlwaysIfInClip_StencilFunc:
294 *mask = clipBit;
295 *ref = clipBit;
296 break;
297 case kEqualIfInClip_StencilFunc:
298 case kLessIfInClip_StencilFunc:
299 case kLEqualIfInClip_StencilFunc:
300 *mask = (*mask & userBits) | clipBit;
301 *ref = (*ref & userBits) | clipBit;
302 break;
303 case kNonZeroIfInClip_StencilFunc:
304 *mask = (*mask & userBits) | clipBit;
305 *ref = clipBit;
306 break;
307 default:
308 GrCrash("Unknown stencil func");
309 }
310 } else {
311 *mask &= userBits;
312 *ref &= userBits;
313 }
314 }
315}
316
317////////////////////////////////////////////////////////////////////////////////
318
319#define VISUALIZE_COMPLEX_CLIP 0
320
321#if VISUALIZE_COMPLEX_CLIP
322 #include "GrRandom.h"
323 GrRandom gRandom;
324 #define SET_RANDOM_COLOR this->setColor(0xff000000 | gRandom.nextU());
325#else
326 #define SET_RANDOM_COLOR
327#endif
328
bsalomon@google.comffca4002011-02-22 20:34:01 +0000329bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000330 const GrIRect* r = NULL;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000331 GrIRect clipRect;
reed@google.comac10a2d2010-12-22 21:39:39 +0000332
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000333 // we check this early because we need a valid
334 // render target to setup stencil clipping
335 // before even going into flushGraphicsState
336 if (NULL == fCurrDrawState.fRenderTarget) {
337 GrAssert(!"No render target bound.");
338 return false;
339 }
340
reed@google.comac10a2d2010-12-22 21:39:39 +0000341 if (fCurrDrawState.fFlagBits & kClip_StateBit) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000342 GrRenderTarget& rt = *fCurrDrawState.fRenderTarget;
343
344 GrRect bounds;
345 GrRect rtRect;
346 rtRect.setLTRB(0, 0,
347 GrIntToScalar(rt.width()), GrIntToScalar(rt.height()));
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000348 if (fClip.hasConservativeBounds()) {
349 bounds = fClip.getConservativeBounds();
bsalomon@google.comd302f142011-03-03 13:54:13 +0000350 bounds.intersectWith(rtRect);
351 } else {
352 bounds = rtRect;
353 }
354
355 bounds.roundOut(&clipRect);
356 if (clipRect.isEmpty()) {
357 clipRect.setLTRB(0,0,0,0);
358 }
359 r = &clipRect;
360
361 fClipState.fClipInStencil = !fClip.isRect() &&
362 !fClip.isEmpty() &&
363 !bounds.isEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000364
365 if (fClipState.fClipInStencil &&
366 (fClipState.fClipIsDirty ||
bsalomon@google.comd302f142011-03-03 13:54:13 +0000367 fClip != rt.fLastStencilClip)) {
368
369 rt.fLastStencilClip = fClip;
370 // we set the current clip to the bounds so that our recursive
371 // draws are scissored to them. We use the copy of the complex clip
372 // in the rt to render
373 const GrClip& clip = rt.fLastStencilClip;
374 fClip.setFromRect(bounds);
reed@google.comac10a2d2010-12-22 21:39:39 +0000375
376 AutoStateRestore asr(this);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000377 AutoInternalDrawGeomRestore aidgr(this);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000378
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000379 this->setViewMatrix(GrMatrix::I());
bsalomon@google.comd302f142011-03-03 13:54:13 +0000380 this->eraseStencilClip(clipRect);
381 this->flushScissor(NULL);
382#if !VISUALIZE_COMPLEX_CLIP
383 this->enableState(kNoColorWrites_StateBit);
384#else
385 this->disableState(kNoColorWrites_StateBit);
386#endif
387 int count = clip.getElementCount();
388 int clipBit = rt.stencilBits();
389 clipBit = (1 << (clipBit-1));
390
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000391 // often we'll see the first two elements of the clip are
392 // the full rt size and another element intersected with it.
393 // We can skip the first full-size rect and save a big rect draw.
394 int firstElement = 0;
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000395 if (clip.getElementCount() > 1 &&
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000396 kRect_ClipType == clip.getElementType(0) &&
397 kIntersect_SetOp == clip.getOp(1)&&
398 clip.getRect(0).contains(bounds)) {
399 firstElement = 1;
400 }
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000401
bsalomon@google.comd302f142011-03-03 13:54:13 +0000402 // walk through each clip element and perform its set op
403 // with the existing clip.
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000404 for (int c = firstElement; c < count; ++c) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000405 GrPathFill fill;
406 // enabled at bottom of loop
407 this->disableState(kModifyStencilClip_StateBit);
408
409 bool canDrawDirectToClip;
410 if (kRect_ClipType == clip.getElementType(c)) {
411 canDrawDirectToClip = true;
412 fill = kEvenOdd_PathFill;
413 } else {
414 fill = clip.getPathFill(c);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000415 GrPathRenderer* pr = this->getPathRenderer();
416 canDrawDirectToClip = pr->requiresStencilPass(this, clip.getPath(c), fill);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000417 }
418
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000419 GrSetOp op = firstElement == c ? kReplace_SetOp : clip.getOp(c);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000420 int passes;
421 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
422
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000423 canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, canDrawDirectToClip,
424 clipBit, IsFillInverted(fill),
bsalomon@google.comd302f142011-03-03 13:54:13 +0000425 &passes, stencilSettings);
426
427 // draw the element to the client stencil bits if necessary
428 if (!canDrawDirectToClip) {
429 if (kRect_ClipType == clip.getElementType(c)) {
430 static const GrStencilSettings gDrawToStencil = {
431 kIncClamp_StencilOp, kIncClamp_StencilOp,
432 kIncClamp_StencilOp, kIncClamp_StencilOp,
433 kAlways_StencilFunc, kAlways_StencilFunc,
434 0xffffffff, 0xffffffff,
435 0x00000000, 0x00000000,
436 0xffffffff, 0xffffffff,
437 };
438 this->setStencil(gDrawToStencil);
439 SET_RANDOM_COLOR
440 this->drawSimpleRect(clip.getRect(c), NULL, 0);
441 } else {
442 SET_RANDOM_COLOR
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000443 getPathRenderer()->drawPathToStencil(this, clip.getPath(c),
444 NonInvertedFill(fill),
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000445 NULL);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000446 }
447 }
448
449 // now we modify the clip bit by rendering either the clip
450 // element directly or a bounding rect of the entire clip.
451 this->enableState(kModifyStencilClip_StateBit);
452 for (int p = 0; p < passes; ++p) {
453 this->setStencil(stencilSettings[p]);
454 if (canDrawDirectToClip) {
455 if (kRect_ClipType == clip.getElementType(c)) {
456 SET_RANDOM_COLOR
457 this->drawSimpleRect(clip.getRect(c), NULL, 0);
458 } else {
459 SET_RANDOM_COLOR
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000460 getPathRenderer()->drawPath(this, 0,
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000461 clip.getPath(c),
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000462 fill, NULL);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000463 }
464 } else {
465 SET_RANDOM_COLOR
466 this->drawSimpleRect(bounds, 0, NULL);
467 }
468 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000469 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000470 fClip = clip;
471 // recusive draws would have disabled this.
472 fClipState.fClipInStencil = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000473 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000474
reed@google.comac10a2d2010-12-22 21:39:39 +0000475 fClipState.fClipIsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000476 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000477
reed@google.comac10a2d2010-12-22 21:39:39 +0000478 // Must flush the scissor after graphics state
bsalomon@google.comd302f142011-03-03 13:54:13 +0000479 if (!this->flushGraphicsState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000480 return false;
481 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000482 this->flushScissor(r);
reed@google.comac10a2d2010-12-22 21:39:39 +0000483 return true;
484}
485
bsalomon@google.comd302f142011-03-03 13:54:13 +0000486////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000487
bsalomon@google.comffca4002011-02-22 20:34:01 +0000488void GrGpu::drawIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000489 int startVertex,
490 int startIndex,
491 int vertexCount,
492 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000493 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
494 fReservedGeometry.fLocked);
495 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
496 fReservedGeometry.fLocked);
497
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000498 this->handleDirtyContext();
499
500 if (!this->setupClipAndFlushState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000501 return;
502 }
503
504#if GR_COLLECT_STATS
505 fStats.fVertexCnt += vertexCount;
506 fStats.fIndexCnt += indexCount;
507 fStats.fDrawCnt += 1;
508#endif
509
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000510 int sVertex = startVertex;
511 int sIndex = startIndex;
512 setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000513
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000514 drawIndexedHelper(type, sVertex, sIndex,
reed@google.comac10a2d2010-12-22 21:39:39 +0000515 vertexCount, indexCount);
516}
517
bsalomon@google.comffca4002011-02-22 20:34:01 +0000518void GrGpu::drawNonIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000519 int startVertex,
520 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000521 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
522 fReservedGeometry.fLocked);
523
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000524 this->handleDirtyContext();
525
526 if (!this->setupClipAndFlushState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000527 return;
528 }
529#if GR_COLLECT_STATS
530 fStats.fVertexCnt += vertexCount;
531 fStats.fDrawCnt += 1;
532#endif
533
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000534 int sVertex = startVertex;
535 setupGeometry(&sVertex, NULL, vertexCount, 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000536
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000537 drawNonIndexedHelper(type, sVertex, vertexCount);
538}
539
540void GrGpu::finalizeReservedVertices() {
541 GrAssert(NULL != fVertexPool);
542 fVertexPool->unlock();
543}
544
545void GrGpu::finalizeReservedIndices() {
546 GrAssert(NULL != fIndexPool);
547 fIndexPool->unlock();
548}
549
550void GrGpu::prepareVertexPool() {
551 if (NULL == fVertexPool) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000552 fVertexPool = new GrVertexBufferAllocPool(this, true,
553 VERTEX_POOL_VB_SIZE,
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +0000554 VERTEX_POOL_VB_COUNT);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000555 } else if (!fVertexPoolInUse) {
556 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000557 fVertexPool->reset();
558 }
559}
560
561void GrGpu::prepareIndexPool() {
562 if (NULL == fVertexPool) {
563 fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000564 } else if (!fIndexPoolInUse) {
565 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000566 fIndexPool->reset();
567 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000568}
569
570bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
571 void** vertices,
572 void** indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000573 GrAssert(!fReservedGeometry.fLocked);
574 size_t reservedVertexSpace = 0;
575
576 if (fReservedGeometry.fVertexCount) {
577 GrAssert(NULL != vertices);
578
bsalomon@google.comd302f142011-03-03 13:54:13 +0000579 this->prepareVertexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000580
581 *vertices = fVertexPool->makeSpace(vertexLayout,
582 fReservedGeometry.fVertexCount,
583 &fCurrPoolVertexBuffer,
584 &fCurrPoolStartVertex);
585 if (NULL == *vertices) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000586 return false;
587 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000588 reservedVertexSpace = VertexSize(vertexLayout) *
589 fReservedGeometry.fVertexCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000590 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000591 if (fReservedGeometry.fIndexCount) {
592 GrAssert(NULL != indices);
593
bsalomon@google.comd302f142011-03-03 13:54:13 +0000594 this->prepareIndexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000595
596 *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
597 &fCurrPoolIndexBuffer,
598 &fCurrPoolStartIndex);
599 if (NULL == *indices) {
600 fVertexPool->putBack(reservedVertexSpace);
601 fCurrPoolVertexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000602 return false;
603 }
604 }
605 return true;
606}
607
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000608void GrGpu::releaseGeometryHelper() {}
609
610void GrGpu::setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount) {
611 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
612 prepareVertexPool();
613#if GR_DEBUG
614 bool success =
615#endif
616 fVertexPool->appendVertices(fGeometrySrc.fVertexLayout,
617 vertexCount,
618 vertexArray,
619 &fCurrPoolVertexBuffer,
620 &fCurrPoolStartVertex);
621 GR_DEBUGASSERT(success);
622}
623
624void GrGpu::setIndexSourceToArrayHelper(const void* indexArray, int indexCount) {
625 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
626 prepareIndexPool();
627#if GR_DEBUG
628 bool success =
629#endif
630 fIndexPool->appendIndices(indexCount,
631 indexArray,
632 &fCurrPoolIndexBuffer,
633 &fCurrPoolStartIndex);
634 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000635}
636
bsalomon@google.comd302f142011-03-03 13:54:13 +0000637////////////////////////////////////////////////////////////////////////////////
638
639GrPathRenderer* GrGpu::getPathRenderer() {
640 if (NULL == fPathRenderer) {
641 fPathRenderer = new GrDefaultPathRenderer(this->supportsTwoSidedStencil(),
642 this->supportsStencilWrapOps());
643 }
644 return fPathRenderer;
645}
646
647////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000648
649const GrGpu::Stats& GrGpu::getStats() const {
650 return fStats;
651}
652
653void GrGpu::resetStats() {
654 memset(&fStats, 0, sizeof(fStats));
655}
656
657void GrGpu::printStats() const {
658 if (GR_COLLECT_STATS) {
659 GrPrintf(
660 "-v-------------------------GPU STATS----------------------------v-\n"
661 "Stats collection is: %s\n"
662 "Draws: %04d, Verts: %04d, Indices: %04d\n"
663 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
664 "TexCreates: %04d, RTCreates:%04d\n"
665 "-^--------------------------------------------------------------^-\n",
666 (GR_COLLECT_STATS ? "ON" : "OFF"),
667 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
668 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
669 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
670 }
671}
672
673////////////////////////////////////////////////////////////////////////////////
674
675GrTexture::~GrTexture() {
676 // use this to set a break-point if needed
677// Gr_clz(3);
678}
679
680const GrSamplerState GrSamplerState::gClampNoFilter(
681 GrSamplerState::kClamp_WrapMode,
682 GrSamplerState::kClamp_WrapMode,
683 GrSamplerState::kNormal_SampleMode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000684 GrMatrix::I(),
reed@google.comac10a2d2010-12-22 21:39:39 +0000685 false);
686
687
688
689