blob: 2d763e299a5a4b0d4fb27c501de0f911a5f8d589 [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
417 bool canDrawDirectToClip;
418 if (kRect_ClipType == clip.getElementType(c)) {
419 canDrawDirectToClip = true;
420 fill = kEvenOdd_PathFill;
421 } else {
422 fill = clip.getPathFill(c);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000423 GrPathRenderer* pr = this->getPathRenderer();
424 canDrawDirectToClip = pr->requiresStencilPass(this, clip.getPath(c), fill);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000425 }
426
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000427 GrSetOp op = firstElement == c ? kReplace_SetOp : clip.getOp(c);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000428 int passes;
429 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
430
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000431 canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, canDrawDirectToClip,
432 clipBit, IsFillInverted(fill),
bsalomon@google.comd302f142011-03-03 13:54:13 +0000433 &passes, stencilSettings);
434
435 // draw the element to the client stencil bits if necessary
436 if (!canDrawDirectToClip) {
437 if (kRect_ClipType == clip.getElementType(c)) {
438 static const GrStencilSettings gDrawToStencil = {
439 kIncClamp_StencilOp, kIncClamp_StencilOp,
440 kIncClamp_StencilOp, kIncClamp_StencilOp,
441 kAlways_StencilFunc, kAlways_StencilFunc,
442 0xffffffff, 0xffffffff,
443 0x00000000, 0x00000000,
444 0xffffffff, 0xffffffff,
445 };
446 this->setStencil(gDrawToStencil);
447 SET_RANDOM_COLOR
448 this->drawSimpleRect(clip.getRect(c), NULL, 0);
449 } else {
450 SET_RANDOM_COLOR
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000451 getPathRenderer()->drawPathToStencil(this, clip.getPath(c),
452 NonInvertedFill(fill),
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000453 NULL);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000454 }
455 }
456
457 // now we modify the clip bit by rendering either the clip
458 // element directly or a bounding rect of the entire clip.
459 this->enableState(kModifyStencilClip_StateBit);
460 for (int p = 0; p < passes; ++p) {
461 this->setStencil(stencilSettings[p]);
462 if (canDrawDirectToClip) {
463 if (kRect_ClipType == clip.getElementType(c)) {
464 SET_RANDOM_COLOR
465 this->drawSimpleRect(clip.getRect(c), NULL, 0);
466 } else {
467 SET_RANDOM_COLOR
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000468 getPathRenderer()->drawPath(this, 0,
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000469 clip.getPath(c),
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000470 fill, NULL);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000471 }
472 } else {
473 SET_RANDOM_COLOR
474 this->drawSimpleRect(bounds, 0, NULL);
475 }
476 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000477 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000478 fClip = clip;
479 // recusive draws would have disabled this.
480 fClipState.fClipInStencil = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000481 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000482
reed@google.comac10a2d2010-12-22 21:39:39 +0000483 fClipState.fClipIsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000484 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000485
reed@google.comac10a2d2010-12-22 21:39:39 +0000486 // Must flush the scissor after graphics state
bsalomon@google.comd302f142011-03-03 13:54:13 +0000487 if (!this->flushGraphicsState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000488 return false;
489 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000490 this->flushScissor(r);
reed@google.comac10a2d2010-12-22 21:39:39 +0000491 return true;
492}
493
bsalomon@google.comd302f142011-03-03 13:54:13 +0000494////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000495
bsalomon@google.comffca4002011-02-22 20:34:01 +0000496void GrGpu::drawIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000497 int startVertex,
498 int startIndex,
499 int vertexCount,
500 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000501 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
502 fReservedGeometry.fLocked);
503 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
504 fReservedGeometry.fLocked);
505
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000506 this->handleDirtyContext();
507
508 if (!this->setupClipAndFlushState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000509 return;
510 }
511
512#if GR_COLLECT_STATS
513 fStats.fVertexCnt += vertexCount;
514 fStats.fIndexCnt += indexCount;
515 fStats.fDrawCnt += 1;
516#endif
517
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000518 int sVertex = startVertex;
519 int sIndex = startIndex;
520 setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000521
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000522 drawIndexedHelper(type, sVertex, sIndex,
reed@google.comac10a2d2010-12-22 21:39:39 +0000523 vertexCount, indexCount);
524}
525
bsalomon@google.comffca4002011-02-22 20:34:01 +0000526void GrGpu::drawNonIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000527 int startVertex,
528 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000529 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
530 fReservedGeometry.fLocked);
531
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000532 this->handleDirtyContext();
533
534 if (!this->setupClipAndFlushState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000535 return;
536 }
537#if GR_COLLECT_STATS
538 fStats.fVertexCnt += vertexCount;
539 fStats.fDrawCnt += 1;
540#endif
541
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000542 int sVertex = startVertex;
543 setupGeometry(&sVertex, NULL, vertexCount, 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000544
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000545 drawNonIndexedHelper(type, sVertex, vertexCount);
546}
547
548void GrGpu::finalizeReservedVertices() {
549 GrAssert(NULL != fVertexPool);
550 fVertexPool->unlock();
551}
552
553void GrGpu::finalizeReservedIndices() {
554 GrAssert(NULL != fIndexPool);
555 fIndexPool->unlock();
556}
557
558void GrGpu::prepareVertexPool() {
559 if (NULL == fVertexPool) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000560 fVertexPool = new GrVertexBufferAllocPool(this, true,
561 VERTEX_POOL_VB_SIZE,
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +0000562 VERTEX_POOL_VB_COUNT);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000563 } else if (!fVertexPoolInUse) {
564 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000565 fVertexPool->reset();
566 }
567}
568
569void GrGpu::prepareIndexPool() {
570 if (NULL == fVertexPool) {
571 fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000572 } else if (!fIndexPoolInUse) {
573 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000574 fIndexPool->reset();
575 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000576}
577
578bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
579 void** vertices,
580 void** indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000581 GrAssert(!fReservedGeometry.fLocked);
582 size_t reservedVertexSpace = 0;
583
584 if (fReservedGeometry.fVertexCount) {
585 GrAssert(NULL != vertices);
586
bsalomon@google.comd302f142011-03-03 13:54:13 +0000587 this->prepareVertexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000588
589 *vertices = fVertexPool->makeSpace(vertexLayout,
590 fReservedGeometry.fVertexCount,
591 &fCurrPoolVertexBuffer,
592 &fCurrPoolStartVertex);
593 if (NULL == *vertices) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000594 return false;
595 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000596 reservedVertexSpace = VertexSize(vertexLayout) *
597 fReservedGeometry.fVertexCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000598 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000599 if (fReservedGeometry.fIndexCount) {
600 GrAssert(NULL != indices);
601
bsalomon@google.comd302f142011-03-03 13:54:13 +0000602 this->prepareIndexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000603
604 *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
605 &fCurrPoolIndexBuffer,
606 &fCurrPoolStartIndex);
607 if (NULL == *indices) {
608 fVertexPool->putBack(reservedVertexSpace);
609 fCurrPoolVertexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000610 return false;
611 }
612 }
613 return true;
614}
615
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000616void GrGpu::releaseGeometryHelper() {}
617
618void GrGpu::setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount) {
619 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
620 prepareVertexPool();
621#if GR_DEBUG
622 bool success =
623#endif
624 fVertexPool->appendVertices(fGeometrySrc.fVertexLayout,
625 vertexCount,
626 vertexArray,
627 &fCurrPoolVertexBuffer,
628 &fCurrPoolStartVertex);
629 GR_DEBUGASSERT(success);
630}
631
632void GrGpu::setIndexSourceToArrayHelper(const void* indexArray, int indexCount) {
633 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
634 prepareIndexPool();
635#if GR_DEBUG
636 bool success =
637#endif
638 fIndexPool->appendIndices(indexCount,
639 indexArray,
640 &fCurrPoolIndexBuffer,
641 &fCurrPoolStartIndex);
642 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000643}
644
bsalomon@google.comd302f142011-03-03 13:54:13 +0000645////////////////////////////////////////////////////////////////////////////////
646
647GrPathRenderer* GrGpu::getPathRenderer() {
648 if (NULL == fPathRenderer) {
649 fPathRenderer = new GrDefaultPathRenderer(this->supportsTwoSidedStencil(),
650 this->supportsStencilWrapOps());
651 }
652 return fPathRenderer;
653}
654
655////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000656
657const GrGpu::Stats& GrGpu::getStats() const {
658 return fStats;
659}
660
661void GrGpu::resetStats() {
662 memset(&fStats, 0, sizeof(fStats));
663}
664
665void GrGpu::printStats() const {
666 if (GR_COLLECT_STATS) {
667 GrPrintf(
668 "-v-------------------------GPU STATS----------------------------v-\n"
669 "Stats collection is: %s\n"
670 "Draws: %04d, Verts: %04d, Indices: %04d\n"
671 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
672 "TexCreates: %04d, RTCreates:%04d\n"
673 "-^--------------------------------------------------------------^-\n",
674 (GR_COLLECT_STATS ? "ON" : "OFF"),
675 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
676 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
677 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
678 }
679}
680
681////////////////////////////////////////////////////////////////////////////////
682
683GrTexture::~GrTexture() {
684 // use this to set a break-point if needed
685// Gr_clz(3);
686}
687
688const GrSamplerState GrSamplerState::gClampNoFilter(
689 GrSamplerState::kClamp_WrapMode,
690 GrSamplerState::kClamp_WrapMode,
691 GrSamplerState::kNormal_SampleMode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000692 GrMatrix::I(),
reed@google.comac10a2d2010-12-22 21:39:39 +0000693 false);
694
695
696
697