blob: 75caa7452a88288b5395c97f864906510c7e2714 [file] [log] [blame]
bsalomon@google.com27847de2011-02-22 20:59:41 +00001/*
bsalomon@google.com1da07462011-03-10 14:51:57 +00002 Copyright 2011 Google Inc.
bsalomon@google.com27847de2011-02-22 20:59:41 +00003
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
17#include "GrContext.h"
18#include "GrTypes.h"
19#include "GrTextureCache.h"
20#include "GrTextStrike.h"
21#include "GrMemory.h"
22#include "GrPathIter.h"
23#include "GrClipIterator.h"
24#include "GrIndexBuffer.h"
25#include "GrInOrderDrawBuffer.h"
26#include "GrBufferAllocPool.h"
27#include "GrPathRenderer.h"
28
29#define DEFER_TEXT_RENDERING 1
30
31#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
32
33static const size_t MAX_TEXTURE_CACHE_COUNT = 128;
34static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024;
35
36static const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 18;
37static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
38
39// We are currently only batching Text and drawRectToRect, both
40// of which use the quad index buffer.
41static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 0;
42static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 0;
43
44GrContext* GrContext::Create(GrGpu::Engine engine,
45 GrGpu::Platform3DContext context3D) {
46 GrContext* ctx = NULL;
47 GrGpu* fGpu = GrGpu::Create(engine, context3D);
48 if (NULL != fGpu) {
49 ctx = new GrContext(fGpu);
50 fGpu->unref();
51 }
52 return ctx;
53}
54
55GrContext* GrContext::CreateGLShaderContext() {
56 return GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);
57}
58
59GrContext::~GrContext() {
bsalomon@google.com8fe72472011-03-30 21:26:44 +000060 this->flush();
bsalomon@google.com27847de2011-02-22 20:59:41 +000061 delete fTextureCache;
62 delete fFontCache;
63 delete fDrawBuffer;
64 delete fDrawBufferVBAllocPool;
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +000065 delete fDrawBufferIBAllocPool;
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +000066 GrSafeUnref(fCustomPathRenderer);
bsalomon@google.com205d4602011-04-25 12:43:45 +000067 GrSafeUnref(fAAFillRectIndexBuffer);
68 GrSafeUnref(fAAStrokeRectIndexBuffer);
69 fGpu->unref();
bsalomon@google.com27847de2011-02-22 20:59:41 +000070}
71
bsalomon@google.com8fe72472011-03-30 21:26:44 +000072void GrContext::contextLost() {
bsalomon@google.com205d4602011-04-25 12:43:45 +000073 // abandon first to so destructors
74 // don't try to free the resources in the API.
75 fGpu->abandonResources();
76
bsalomon@google.com8fe72472011-03-30 21:26:44 +000077 delete fDrawBuffer;
78 fDrawBuffer = NULL;
bsalomon@google.com205d4602011-04-25 12:43:45 +000079
bsalomon@google.com8fe72472011-03-30 21:26:44 +000080 delete fDrawBufferVBAllocPool;
81 fDrawBufferVBAllocPool = NULL;
bsalomon@google.com205d4602011-04-25 12:43:45 +000082
bsalomon@google.com8fe72472011-03-30 21:26:44 +000083 delete fDrawBufferIBAllocPool;
84 fDrawBufferIBAllocPool = NULL;
85
bsalomon@google.com205d4602011-04-25 12:43:45 +000086 GrSafeSetNull(fAAFillRectIndexBuffer);
87 GrSafeSetNull(fAAStrokeRectIndexBuffer);
88
bsalomon@google.com8fe72472011-03-30 21:26:44 +000089 fTextureCache->removeAll();
90 fFontCache->freeAll();
91 fGpu->markContextDirty();
92
bsalomon@google.com8fe72472011-03-30 21:26:44 +000093 this->setupDrawBuffer();
94}
95
96void GrContext::resetContext() {
97 fGpu->markContextDirty();
98}
99
100void GrContext::freeGpuResources() {
101 this->flush();
102 fTextureCache->removeAll();
103 fFontCache->freeAll();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000104}
105
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000106////////////////////////////////////////////////////////////////////////////////
107
108
109enum {
110 kNPOTBit = 0x1,
111 kFilterBit = 0x2,
112 kKeylessBit = 0x4,
113};
114
115bool GrContext::finalizeTextureKey(GrTextureKey* key,
116 const GrSamplerState& sampler,
117 bool keyless) const {
118 uint32_t bits = 0;
119 uint16_t width = key->width();
120 uint16_t height = key->height();
121
122 if (!fGpu->npotTextureTileSupport()) {
123 bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
124
125 bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
126 (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
127
128 if (tiled && !isPow2) {
129 bits |= kNPOTBit;
130 if (sampler.isFilter()) {
131 bits |= kFilterBit;
132 }
133 }
134 }
135
136 if (keyless) {
137 bits |= kKeylessBit;
138 }
139 key->finalize(bits);
140 return 0 != bits;
141}
142
bsalomon@google.com27847de2011-02-22 20:59:41 +0000143GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,
144 const GrSamplerState& sampler) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000145 finalizeTextureKey(key, sampler, false);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000146 return fTextureCache->findAndLock(*key);
147}
148
149static void stretchImage(void* dst,
150 int dstW,
151 int dstH,
152 void* src,
153 int srcW,
154 int srcH,
155 int bpp) {
156 GrFixed dx = (srcW << 16) / dstW;
157 GrFixed dy = (srcH << 16) / dstH;
158
159 GrFixed y = dy >> 1;
160
161 int dstXLimit = dstW*bpp;
162 for (int j = 0; j < dstH; ++j) {
163 GrFixed x = dx >> 1;
164 void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
165 void* dstRow = (uint8_t*)dst + j*dstW*bpp;
166 for (int i = 0; i < dstXLimit; i += bpp) {
167 memcpy((uint8_t*) dstRow + i,
168 (uint8_t*) srcRow + (x>>16)*bpp,
169 bpp);
170 x += dx;
171 }
172 y += dy;
173 }
174}
175
176GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
177 const GrSamplerState& sampler,
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000178 const GrTextureDesc& desc,
bsalomon@google.com27847de2011-02-22 20:59:41 +0000179 void* srcData, size_t rowBytes) {
180 GrAssert(key->width() == desc.fWidth);
181 GrAssert(key->height() == desc.fHeight);
182
183#if GR_DUMP_TEXTURE_UPLOAD
184 GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
185#endif
186
187 GrTextureEntry* entry = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000188 bool special = finalizeTextureKey(key, sampler, false);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000189 if (special) {
190 GrTextureEntry* clampEntry;
191 GrTextureKey clampKey(*key);
192 clampEntry = findAndLockTexture(&clampKey, GrSamplerState::ClampNoFilter());
193
194 if (NULL == clampEntry) {
195 clampEntry = createAndLockTexture(&clampKey,
196 GrSamplerState::ClampNoFilter(),
197 desc, srcData, rowBytes);
198 GrAssert(NULL != clampEntry);
199 if (NULL == clampEntry) {
200 return NULL;
201 }
202 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000203 GrTextureDesc rtDesc = desc;
204 rtDesc.fFlags = rtDesc.fFlags |
205 kRenderTarget_GrTextureFlagBit |
206 kNoStencil_GrTextureFlagBit;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000207 rtDesc.fWidth = GrNextPow2(GrMax<int>(desc.fWidth,
208 fGpu->minRenderTargetWidth()));
209 rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
210 fGpu->minRenderTargetHeight()));
211
212 GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
213
214 if (NULL != texture) {
215 GrDrawTarget::AutoStateRestore asr(fGpu);
216 fGpu->setRenderTarget(texture->asRenderTarget());
217 fGpu->setTexture(0, clampEntry->texture());
bsalomon@google.comd302f142011-03-03 13:54:13 +0000218 fGpu->disableStencil();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000219 fGpu->setViewMatrix(GrMatrix::I());
220 fGpu->setAlpha(0xff);
221 fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
222 fGpu->disableState(GrDrawTarget::kDither_StateBit |
223 GrDrawTarget::kClip_StateBit |
224 GrDrawTarget::kAntialias_StateBit);
225 GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,
226 GrSamplerState::kClamp_WrapMode,
227 sampler.isFilter());
228 fGpu->setSamplerState(0, stretchSampler);
229
230 static const GrVertexLayout layout =
231 GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
232 GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
233
234 if (arg.succeeded()) {
235 GrPoint* verts = (GrPoint*) arg.vertices();
236 verts[0].setIRectFan(0, 0,
237 texture->width(),
238 texture->height(),
239 2*sizeof(GrPoint));
240 verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
241 fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
242 0, 4);
243 entry = fTextureCache->createAndLock(*key, texture);
244 }
bsalomon@google.com1da07462011-03-10 14:51:57 +0000245 texture->releaseRenderTarget();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000246 } else {
247 // TODO: Our CPU stretch doesn't filter. But we create separate
248 // stretched textures when the sampler state is either filtered or
249 // not. Either implement filtered stretch blit on CPU or just create
250 // one when FBO case fails.
251
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000252 rtDesc.fFlags = kNone_GrTextureFlags;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000253 // no longer need to clamp at min RT size.
254 rtDesc.fWidth = GrNextPow2(desc.fWidth);
255 rtDesc.fHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000256 int bpp = GrBytesPerPixel(desc.fFormat);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000257 GrAutoSMalloc<128*128*4> stretchedPixels(bpp *
258 rtDesc.fWidth *
259 rtDesc.fHeight);
260 stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
261 srcData, desc.fWidth, desc.fHeight, bpp);
262
263 size_t stretchedRowBytes = rtDesc.fWidth * bpp;
264
265 GrTexture* texture = fGpu->createTexture(rtDesc,
266 stretchedPixels.get(),
267 stretchedRowBytes);
268 GrAssert(NULL != texture);
269 entry = fTextureCache->createAndLock(*key, texture);
270 }
271 fTextureCache->unlock(clampEntry);
272
273 } else {
274 GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
275 if (NULL != texture) {
276 entry = fTextureCache->createAndLock(*key, texture);
277 } else {
278 entry = NULL;
279 }
280 }
281 return entry;
282}
283
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000284GrTextureEntry* GrContext::lockKeylessTexture(const GrTextureDesc& desc,
285 const GrSamplerState& state) {
286 uint32_t p0 = desc.fFormat;
287 uint32_t p1 = (desc.fAALevel << 16) | desc.fFlags;
288 GrTextureKey key(p0, p1, desc.fWidth, desc.fHeight);
289 this->finalizeTextureKey(&key, state, true);
290 GrTextureEntry* entry = fTextureCache->findAndLock(key);
291 if (NULL == entry) {
292 GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
293 if (NULL != texture) {
294 entry = fTextureCache->createAndLock(key, texture);
295 }
296 }
297 // If the caller gives us the same desc/sampler twice we don't want
298 // to return the same texture the second time (unless it was previously
299 // released). So we detach the entry from the cache and reattach at release.
300 if (NULL != entry) {
301 fTextureCache->detach(entry);
302 }
303 return entry;
304}
305
bsalomon@google.com27847de2011-02-22 20:59:41 +0000306void GrContext::unlockTexture(GrTextureEntry* entry) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000307 if (kKeylessBit & entry->key().getPrivateBits()) {
308 fTextureCache->reattachAndUnlock(entry);
309 } else {
310 fTextureCache->unlock(entry);
311 }
bsalomon@google.com27847de2011-02-22 20:59:41 +0000312}
313
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000314GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& desc,
bsalomon@google.com27847de2011-02-22 20:59:41 +0000315 void* srcData,
316 size_t rowBytes) {
317 return fGpu->createTexture(desc, srcData, rowBytes);
318}
319
320void GrContext::getTextureCacheLimits(int* maxTextures,
321 size_t* maxTextureBytes) const {
322 fTextureCache->getLimits(maxTextures, maxTextureBytes);
323}
324
325void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
326 fTextureCache->setLimits(maxTextures, maxTextureBytes);
327}
328
329int GrContext::getMaxTextureDimension() {
330 return fGpu->maxTextureDimension();
331}
332
333///////////////////////////////////////////////////////////////////////////////
334
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000335GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
336 // validate flags here so that GrGpu subclasses don't have to check
337 if (kTexture_GrPlatformSurfaceType == desc.fSurfaceType &&
338 0 != desc.fRenderTargetFlags) {
339 return NULL;
340 }
341 if (!(kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) &&
342 (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
343 return NULL;
344 }
345 if (kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType &&
346 (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) &&
347 !(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
348 return NULL;
349 }
350 return fGpu->createPlatformSurface(desc);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000351}
352
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000353///////////////////////////////////////////////////////////////////////////////
354
bsalomon@google.com27847de2011-02-22 20:59:41 +0000355bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
356 int width, int height) {
357 if (!fGpu->supports8BitPalette()) {
358 return false;
359 }
360
361
362 bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
363
364 if (!isPow2) {
365 if (!fGpu->npotTextureSupport()) {
366 return false;
367 }
368
369 bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
370 sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
371 if (tiled && !fGpu->npotTextureTileSupport()) {
372 return false;
373 }
374 }
375 return true;
376}
377
378////////////////////////////////////////////////////////////////////////////////
379
380void GrContext::setClip(const GrClip& clip) {
381 fGpu->setClip(clip);
382 fGpu->enableState(GrDrawTarget::kClip_StateBit);
383}
384
385void GrContext::setClip(const GrIRect& rect) {
386 GrClip clip;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000387 clip.setFromIRect(rect);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000388 fGpu->setClip(clip);
389}
390
391////////////////////////////////////////////////////////////////////////////////
392
bsalomon@google.com398109c2011-04-14 18:40:27 +0000393void GrContext::clear(GrColor color) {
394 // gpu flush call is immediate, must flush.
395 // (could in theory skip draws to current render target.)
396 this->flush();
397 fGpu->clear(color);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000398}
399
400void GrContext::drawPaint(const GrPaint& paint) {
401 // set rect to be big enough to fill the space, but not super-huge, so we
402 // don't overflow fixed-point implementations
bsalomon@google.comd302f142011-03-03 13:54:13 +0000403 GrRect r;
404 r.setLTRB(0, 0,
405 GrIntToScalar(getRenderTarget()->width()),
406 GrIntToScalar(getRenderTarget()->height()));
bsalomon@google.com27847de2011-02-22 20:59:41 +0000407 GrMatrix inverse;
408 if (fGpu->getViewInverse(&inverse)) {
409 inverse.mapRect(&r);
410 } else {
411 GrPrintf("---- fGpu->getViewInverse failed\n");
412 }
413 this->drawRect(paint, r);
414}
415
bsalomon@google.com205d4602011-04-25 12:43:45 +0000416////////////////////////////////////////////////////////////////////////////////
417
bsalomon@google.com27847de2011-02-22 20:59:41 +0000418/* create a triangle strip that strokes the specified triangle. There are 8
419 unique vertices, but we repreat the last 2 to close up. Alternatively we
420 could use an indices array, and then only send 8 verts, but not sure that
421 would be faster.
422 */
bsalomon@google.com205d4602011-04-25 12:43:45 +0000423static void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
bsalomon@google.com27847de2011-02-22 20:59:41 +0000424 GrScalar width) {
425 const GrScalar rad = GrScalarHalf(width);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000426 rect.sort();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000427
428 verts[0].set(rect.fLeft + rad, rect.fTop + rad);
429 verts[1].set(rect.fLeft - rad, rect.fTop - rad);
430 verts[2].set(rect.fRight - rad, rect.fTop + rad);
431 verts[3].set(rect.fRight + rad, rect.fTop - rad);
432 verts[4].set(rect.fRight - rad, rect.fBottom - rad);
433 verts[5].set(rect.fRight + rad, rect.fBottom + rad);
434 verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
435 verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
436 verts[8] = verts[0];
437 verts[9] = verts[1];
438}
439
bsalomon@google.com205d4602011-04-25 12:43:45 +0000440static GrColor getColorForMesh(const GrPaint& paint) {
441 if (NULL == paint.getTexture()) {
442 return paint.fColor;
443 } else {
444 unsigned a = GrColorUnpackA(paint.fColor);
445 return GrColorPackRGBA(a, a, a, a);
446 }
447}
448
449static void setInsetFan(GrPoint* pts, size_t stride,
450 const GrRect& r, GrScalar dx, GrScalar dy) {
451 pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride);
452}
453
454static const uint16_t gFillAARectIdx[] = {
455 0, 1, 5, 5, 4, 0,
456 1, 2, 6, 6, 5, 1,
457 2, 3, 7, 7, 6, 2,
458 3, 0, 4, 4, 7, 3,
459 4, 5, 6, 6, 7, 4,
460};
461
462int GrContext::aaFillRectIndexCount() const {
463 return GR_ARRAY_COUNT(gFillAARectIdx);
464}
465
466GrIndexBuffer* GrContext::aaFillRectIndexBuffer() {
467 if (NULL == fAAFillRectIndexBuffer) {
468 fAAFillRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gFillAARectIdx),
469 false);
470 GrAssert(NULL != fAAFillRectIndexBuffer);
471#if GR_DEBUG
472 bool updated =
473#endif
474 fAAFillRectIndexBuffer->updateData(gFillAARectIdx,
475 sizeof(gFillAARectIdx));
476 GR_DEBUGASSERT(updated);
477 }
478 return fAAFillRectIndexBuffer;
479}
480
481static const uint16_t gStrokeAARectIdx[] = {
482 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
483 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
484 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
485 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
486
487 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
488 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
489 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
490 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
491
492 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
493 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
494 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
495 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
496};
497
498int GrContext::aaStrokeRectIndexCount() const {
499 return GR_ARRAY_COUNT(gStrokeAARectIdx);
500}
501
502GrIndexBuffer* GrContext::aaStrokeRectIndexBuffer() {
503 if (NULL == fAAStrokeRectIndexBuffer) {
504 fAAStrokeRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gStrokeAARectIdx),
505 false);
506 GrAssert(NULL != fAAStrokeRectIndexBuffer);
507#if GR_DEBUG
508 bool updated =
509#endif
510 fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
511 sizeof(gStrokeAARectIdx));
512 GR_DEBUGASSERT(updated);
513 }
514 return fAAStrokeRectIndexBuffer;
515}
516
517void GrContext::fillAARect(GrDrawTarget* target,
518 const GrPaint& paint,
519 const GrRect& devRect) {
520
521 GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit;
522 if (NULL != paint.getTexture()) {
523 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
524 }
525
526 size_t vsize = GrDrawTarget::VertexSize(layout);
527
528 GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0);
529
530 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
531
532 GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
533 GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
534
535 setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf);
536 setInsetFan(fan1Pos, vsize, devRect, GR_ScalarHalf, GR_ScalarHalf);
537
538 verts += sizeof(GrPoint);
539 for (int i = 0; i < 4; ++i) {
540 *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
541 }
542
543 GrColor innerColor = getColorForMesh(paint);
544 verts += 4 * vsize;
545 for (int i = 0; i < 4; ++i) {
546 *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
547 }
548
549 target->setIndexSourceToBuffer(this->aaFillRectIndexBuffer());
550
551 target->drawIndexed(kTriangles_PrimitiveType, 0,
552 0, 8, this->aaFillRectIndexCount());
553}
554
555void GrContext::strokeAARect(GrDrawTarget* target, const GrPaint& paint,
556 const GrRect& devRect, const GrVec& devStrokeSize) {
557 const GrScalar& dx = devStrokeSize.fX;
558 const GrScalar& dy = devStrokeSize.fY;
559 const GrScalar rx = GrMul(dx, GR_ScalarHalf);
560 const GrScalar ry = GrMul(dy, GR_ScalarHalf);
561
562 GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit;
563
564 if (NULL != paint.getTexture()) {
565 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
566 }
567
568 GrScalar spare;
569 {
570 GrScalar w = devRect.width() - dx;
571 GrScalar h = devRect.height() - dy;
572 spare = GrMin(w, h);
573 }
574
575 if (spare <= 0) {
576 GrRect r(devRect);
577 r.inset(-rx, -ry);
578 fillAARect(target, paint, r);
579 return;
580 }
581
582 size_t vsize = GrDrawTarget::VertexSize(layout);
583
584 GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0);
585
586 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
587
588 GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
589 GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
590 GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
591 GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
592
593 setInsetFan(fan0Pos, vsize, devRect, -rx - GR_ScalarHalf, -ry - GR_ScalarHalf);
594 setInsetFan(fan1Pos, vsize, devRect, -rx + GR_ScalarHalf, -ry + GR_ScalarHalf);
595 setInsetFan(fan2Pos, vsize, devRect, rx - GR_ScalarHalf, ry - GR_ScalarHalf);
596 setInsetFan(fan3Pos, vsize, devRect, rx + GR_ScalarHalf, ry + GR_ScalarHalf);
597
598 verts += sizeof(GrPoint);
599 for (int i = 0; i < 4; ++i) {
600 *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
601 }
602
603 GrColor innerColor = getColorForMesh(paint);
604 verts += 4 * vsize;
605 for (int i = 0; i < 8; ++i) {
606 *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
607 }
608
609 verts += 8 * vsize;
610 for (int i = 0; i < 8; ++i) {
611 *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
612 }
613
614 target->setIndexSourceToBuffer(aaStrokeRectIndexBuffer());
615 target->drawIndexed(kTriangles_PrimitiveType,
616 0, 0, 16, aaStrokeRectIndexCount());
617}
618
619static bool apply_aa_to_rect(GrDrawTarget* target,
620 GrGpu* gpu,
621 const GrPaint& paint,
622 const GrRect& rect,
623 GrScalar width,
624 const GrMatrix* matrix,
625 GrMatrix* combinedMatrix,
626 GrRect* devRect) {
627 // we use a simple alpha ramp to do aa on axis-aligned rects
628 // do AA with alpha ramp if the caller requested AA, the rect
629 // will be axis-aligned,the render target is not
630 // multisampled, and the rect won't land on integer coords.
631
632 if (!paint.fAntiAlias) {
633 return false;
634 }
635
636 if (target->getRenderTarget()->isMultisampled()) {
637 return false;
638 }
639
640 if (0 == width && gpu->supportsAALines()) {
641 return false;
642 }
643
644 if (!target->getViewMatrix().preservesAxisAlignment()) {
645 return false;
646 }
647
648 if (NULL != matrix &&
649 !matrix->preservesAxisAlignment()) {
650 return false;
651 }
652
653 *combinedMatrix = target->getViewMatrix();
654 if (NULL != matrix) {
655 combinedMatrix->preConcat(*matrix);
656 GrAssert(combinedMatrix->preservesAxisAlignment());
657 }
658
659 combinedMatrix->mapRect(devRect, rect);
660 devRect->sort();
661
662 if (width < 0) {
663 return !devRect->isIRect();
664 } else {
665 return true;
666 }
667}
668
bsalomon@google.com27847de2011-02-22 20:59:41 +0000669void GrContext::drawRect(const GrPaint& paint,
670 const GrRect& rect,
671 GrScalar width,
672 const GrMatrix* matrix) {
673
674 bool textured = NULL != paint.getTexture();
675
676 GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
677
bsalomon@google.com205d4602011-04-25 12:43:45 +0000678 GrRect devRect = rect;
679 GrMatrix combinedMatrix;
680 bool doAA = apply_aa_to_rect(target, fGpu, paint, rect, width, matrix,
681 &combinedMatrix, &devRect);
682
683 if (doAA) {
684 GrDrawTarget::AutoViewMatrixRestore avm(target);
685 if (textured) {
686 GrMatrix inv;
687 if (combinedMatrix.invert(&inv)) {
688 target->preConcatSamplerMatrix(0, inv);
689 }
690 }
691 target->setViewMatrix(GrMatrix::I());
692 if (width >= 0) {
693 GrVec strokeSize;;
694 if (width > 0) {
695 strokeSize.set(width, width);
696 combinedMatrix.mapVec(&strokeSize);
697 strokeSize.setAbs(strokeSize);
698 } else {
699 strokeSize.set(GR_Scalar1, GR_Scalar1);
700 }
701 strokeAARect(target, paint, devRect, strokeSize);
702 } else {
703 fillAARect(target, paint, devRect);
704 }
705 return;
706 }
707
bsalomon@google.com27847de2011-02-22 20:59:41 +0000708 if (width >= 0) {
709 // TODO: consider making static vertex buffers for these cases.
710 // Hairline could be done by just adding closing vertex to
711 // unitSquareVertexBuffer()
bsalomon@google.com205d4602011-04-25 12:43:45 +0000712 GrVertexLayout layout = textured ?
713 GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
714 0;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000715 static const int worstCaseVertCount = 10;
716 GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
717
718 if (!geo.succeeded()) {
719 return;
720 }
721
722 GrPrimitiveType primType;
723 int vertCount;
724 GrPoint* vertex = geo.positions();
725
726 if (width > 0) {
727 vertCount = 10;
728 primType = kTriangleStrip_PrimitiveType;
729 setStrokeRectStrip(vertex, rect, width);
730 } else {
731 // hairline
732 vertCount = 5;
733 primType = kLineStrip_PrimitiveType;
734 vertex[0].set(rect.fLeft, rect.fTop);
735 vertex[1].set(rect.fRight, rect.fTop);
736 vertex[2].set(rect.fRight, rect.fBottom);
737 vertex[3].set(rect.fLeft, rect.fBottom);
738 vertex[4].set(rect.fLeft, rect.fTop);
739 }
740
741 GrDrawTarget::AutoViewMatrixRestore avmr;
742 if (NULL != matrix) {
743 avmr.set(target);
744 target->preConcatViewMatrix(*matrix);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000745 if (textured) {
746 target->preConcatSamplerMatrix(0, *matrix);
747 }
bsalomon@google.com27847de2011-02-22 20:59:41 +0000748 }
749
750 target->drawNonIndexed(primType, 0, vertCount);
751 } else {
752 #if GR_STATIC_RECT_VB
753 GrVertexLayout layout = (textured) ?
754 GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
755 0;
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +0000756 target->setVertexSourceToBuffer(layout,
bsalomon@google.com27847de2011-02-22 20:59:41 +0000757 fGpu->getUnitSquareVertexBuffer());
758 GrDrawTarget::AutoViewMatrixRestore avmr(target);
759 GrMatrix m;
760 m.setAll(rect.width(), 0, rect.fLeft,
bsalomon@google.com205d4602011-04-25 12:43:45 +0000761 0, rect.height(), rect.fTop,
762 0, 0, GrMatrix::I()[8]);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000763
764 if (NULL != matrix) {
765 m.postConcat(*matrix);
766 }
767
768 target->preConcatViewMatrix(m);
769
770 if (textured) {
771 target->preConcatSamplerMatrix(0, m);
772 }
773 target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
774 #else
775 target->drawSimpleRect(rect, matrix, textured ? 1 : 0);
776 #endif
777 }
778}
779
780void GrContext::drawRectToRect(const GrPaint& paint,
781 const GrRect& dstRect,
782 const GrRect& srcRect,
783 const GrMatrix* dstMatrix,
784 const GrMatrix* srcMatrix) {
785
786 if (NULL == paint.getTexture()) {
787 drawRect(paint, dstRect, -1, dstMatrix);
788 return;
789 }
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +0000790
bsalomon@google.com27847de2011-02-22 20:59:41 +0000791 GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
792
793#if GR_STATIC_RECT_VB
794 GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
795
796 GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
797 GrDrawTarget::AutoViewMatrixRestore avmr(target);
798
799 GrMatrix m;
800
801 m.setAll(dstRect.width(), 0, dstRect.fLeft,
802 0, dstRect.height(), dstRect.fTop,
803 0, 0, GrMatrix::I()[8]);
804 if (NULL != dstMatrix) {
805 m.postConcat(*dstMatrix);
806 }
807 target->preConcatViewMatrix(m);
808
809 m.setAll(srcRect.width(), 0, srcRect.fLeft,
810 0, srcRect.height(), srcRect.fTop,
811 0, 0, GrMatrix::I()[8]);
812 if (NULL != srcMatrix) {
813 m.postConcat(*srcMatrix);
814 }
815 target->preConcatSamplerMatrix(0, m);
816
817 target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());
818 target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
819#else
820
821 GrDrawTarget* target;
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +0000822#if BATCH_RECT_TO_RECT
bsalomon@google.com27847de2011-02-22 20:59:41 +0000823 target = this->prepareToDraw(paint, kBuffered_DrawCategory);
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +0000824#else
bsalomon@google.com27847de2011-02-22 20:59:41 +0000825 target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
826#endif
827
828 const GrRect* srcRects[GrDrawTarget::kNumStages] = {NULL};
829 const GrMatrix* srcMatrices[GrDrawTarget::kNumStages] = {NULL};
830 srcRects[0] = &srcRect;
831 srcMatrices[0] = srcMatrix;
832
833 target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
834#endif
835}
836
837void GrContext::drawVertices(const GrPaint& paint,
838 GrPrimitiveType primitiveType,
839 int vertexCount,
840 const GrPoint positions[],
841 const GrPoint texCoords[],
842 const GrColor colors[],
843 const uint16_t indices[],
844 int indexCount) {
845 GrVertexLayout layout = 0;
846 int vertexSize = sizeof(GrPoint);
847
848 GrDrawTarget::AutoReleaseGeometry geo;
849
850 GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
851
852 if (NULL != paint.getTexture()) {
853 if (NULL == texCoords) {
854 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
855 } else {
856 layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
857 vertexSize += sizeof(GrPoint);
858 }
859 }
860
861 if (NULL != colors) {
862 layout |= GrDrawTarget::kColor_VertexLayoutBit;
863 vertexSize += sizeof(GrColor);
864 }
865
866 if (sizeof(GrPoint) != vertexSize) {
867 if (!geo.set(target, layout, vertexCount, 0)) {
868 GrPrintf("Failed to get space for vertices!");
869 return;
870 }
871 int texOffsets[GrDrawTarget::kMaxTexCoords];
872 int colorOffset;
873 int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
874 texOffsets,
875 &colorOffset);
876 void* curVertex = geo.vertices();
877
878 for (int i = 0; i < vertexCount; ++i) {
879 *((GrPoint*)curVertex) = positions[i];
880
881 if (texOffsets[0] > 0) {
882 *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
883 }
884 if (colorOffset > 0) {
885 *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
886 }
887 curVertex = (void*)((intptr_t)curVertex + vsize);
888 }
889 } else {
890 target->setVertexSourceToArray(layout, positions, vertexCount);
891 }
892
893 if (NULL != indices) {
894 target->setIndexSourceToArray(indices, indexCount);
895 target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
896 } else {
897 target->drawNonIndexed(primitiveType, 0, vertexCount);
898 }
899}
900
901
902////////////////////////////////////////////////////////////////////////////////
903
904void GrContext::drawPath(const GrPaint& paint,
905 GrPathIter* path,
906 GrPathFill fill,
907 const GrPoint* translate) {
908
909
910 GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
911
912 GrDrawTarget::StageBitfield enabledStages = 0;
913 if (NULL != paint.getTexture()) {
914 enabledStages |= 1;
915 }
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000916 GrPathRenderer* pr = getPathRenderer(target, path, fill);
917 pr->drawPath(target, enabledStages, path, fill, translate);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000918}
919
bsalomon@google.comd302f142011-03-03 13:54:13 +0000920void GrContext::drawPath(const GrPaint& paint,
921 const GrPath& path,
922 GrPathFill fill,
923 const GrPoint* translate) {
924 GrPath::Iter iter(path);
925 this->drawPath(paint, &iter, fill, translate);
926}
927
928
bsalomon@google.com27847de2011-02-22 20:59:41 +0000929////////////////////////////////////////////////////////////////////////////////
930
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000931void GrContext::flush(int flagsBitfield) {
932 if (kDiscard_FlushBit & flagsBitfield) {
933 fDrawBuffer->reset();
934 } else {
935 flushDrawBuffer();
936 }
937
938 if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
bsalomon@google.com27847de2011-02-22 20:59:41 +0000939 fGpu->forceRenderTargetFlush();
940 }
941}
942
943void GrContext::flushText() {
944 if (kText_DrawCategory == fLastDrawCategory) {
945 flushDrawBuffer();
946 }
947}
948
949void GrContext::flushDrawBuffer() {
950#if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
951 fDrawBuffer->playback(fGpu);
952 fDrawBuffer->reset();
953#endif
954}
955
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000956bool GrContext::readTexturePixels(GrTexture* texture,
957 int left, int top, int width, int height,
958 GrPixelConfig config, void* buffer) {
959
960 // TODO: code read pixels for textures that aren't rendertargets
961
962 this->flush();
963 GrRenderTarget* target = texture->asRenderTarget();
964 if (NULL != target) {
965 return fGpu->readPixels(target,
966 left, top, width, height,
967 config, buffer);
968 } else {
969 return false;
970 }
971}
972
973bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
974 int left, int top, int width, int height,
975 GrPixelConfig config, void* buffer) {
976 uint32_t flushFlags = 0;
977 if (NULL == target) {
978 flushFlags |= GrContext::kForceCurrentRenderTarget_FlushBit;
979 }
980
981 this->flush(flushFlags);
982 return fGpu->readPixels(target,
983 left, top, width, height,
984 config, buffer);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000985}
986
987void GrContext::writePixels(int left, int top, int width, int height,
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000988 GrPixelConfig config, const void* buffer,
bsalomon@google.com27847de2011-02-22 20:59:41 +0000989 size_t stride) {
990
991 // TODO: when underlying api has a direct way to do this we should use it
992 // (e.g. glDrawPixels on desktop GL).
993
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000994 const GrTextureDesc desc = {
995 kNone_GrTextureFlags, kNone_GrAALevel, width, height, config
bsalomon@google.com27847de2011-02-22 20:59:41 +0000996 };
997 GrTexture* texture = fGpu->createTexture(desc, buffer, stride);
998 if (NULL == texture) {
999 return;
1000 }
1001
1002 this->flush(true);
1003
1004 GrAutoUnref aur(texture);
1005 GrDrawTarget::AutoStateRestore asr(fGpu);
1006
1007 GrMatrix matrix;
1008 matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
1009 fGpu->setViewMatrix(matrix);
1010
1011 fGpu->disableState(GrDrawTarget::kClip_StateBit);
1012 fGpu->setAlpha(0xFF);
1013 fGpu->setBlendFunc(kOne_BlendCoeff,
1014 kZero_BlendCoeff);
1015 fGpu->setTexture(0, texture);
1016
1017 GrSamplerState sampler;
1018 sampler.setClampNoFilter();
1019 matrix.setScale(GR_Scalar1 / width, GR_Scalar1 / height);
1020 sampler.setMatrix(matrix);
1021 fGpu->setSamplerState(0, sampler);
1022
1023 GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
1024 static const int VCOUNT = 4;
1025
1026 GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
1027 if (!geo.succeeded()) {
1028 return;
1029 }
1030 ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
1031 fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);
1032}
1033////////////////////////////////////////////////////////////////////////////////
1034
1035void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
1036 target->setTexture(0, paint.getTexture());
1037 target->setSamplerState(0, paint.fSampler);
1038 target->setColor(paint.fColor);
1039
1040 if (paint.fDither) {
1041 target->enableState(GrDrawTarget::kDither_StateBit);
1042 } else {
1043 target->disableState(GrDrawTarget::kDither_StateBit);
1044 }
1045 if (paint.fAntiAlias) {
1046 target->enableState(GrDrawTarget::kAntialias_StateBit);
1047 } else {
1048 target->disableState(GrDrawTarget::kAntialias_StateBit);
1049 }
1050 target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
1051}
1052
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +00001053GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
bsalomon@google.com27847de2011-02-22 20:59:41 +00001054 DrawCategory category) {
1055 if (category != fLastDrawCategory) {
1056 flushDrawBuffer();
1057 fLastDrawCategory = category;
1058 }
1059 SetPaint(paint, fGpu);
1060 GrDrawTarget* target = fGpu;
1061 switch (category) {
1062 case kText_DrawCategory:
1063#if DEFER_TEXT_RENDERING
1064 target = fDrawBuffer;
1065 fDrawBuffer->initializeDrawStateAndClip(*fGpu);
1066#else
1067 target = fGpu;
1068#endif
1069 break;
1070 case kUnbuffered_DrawCategory:
1071 target = fGpu;
1072 break;
1073 case kBuffered_DrawCategory:
1074 target = fDrawBuffer;
1075 fDrawBuffer->initializeDrawStateAndClip(*fGpu);
1076 break;
1077 }
1078 return target;
1079}
1080
1081////////////////////////////////////////////////////////////////////////////////
1082
bsalomon@google.com27847de2011-02-22 20:59:41 +00001083void GrContext::setRenderTarget(GrRenderTarget* target) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001084 this->flush(false);
bsalomon@google.com27847de2011-02-22 20:59:41 +00001085 fGpu->setRenderTarget(target);
1086}
1087
1088GrRenderTarget* GrContext::getRenderTarget() {
1089 return fGpu->getRenderTarget();
1090}
1091
1092const GrRenderTarget* GrContext::getRenderTarget() const {
1093 return fGpu->getRenderTarget();
1094}
1095
1096const GrMatrix& GrContext::getMatrix() const {
1097 return fGpu->getViewMatrix();
1098}
1099
1100void GrContext::setMatrix(const GrMatrix& m) {
1101 fGpu->setViewMatrix(m);
1102}
1103
1104void GrContext::concatMatrix(const GrMatrix& m) const {
1105 fGpu->preConcatViewMatrix(m);
1106}
1107
1108static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
1109 intptr_t mask = 1 << shift;
1110 if (pred) {
1111 bits |= mask;
1112 } else {
1113 bits &= ~mask;
1114 }
1115 return bits;
1116}
1117
1118void GrContext::resetStats() {
1119 fGpu->resetStats();
1120}
1121
1122const GrGpu::Stats& GrContext::getStats() const {
1123 return fGpu->getStats();
1124}
1125
1126void GrContext::printStats() const {
1127 fGpu->printStats();
1128}
1129
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +00001130GrContext::GrContext(GrGpu* gpu) :
1131 fDefaultPathRenderer(gpu->supportsTwoSidedStencil(),
1132 gpu->supportsStencilWrapOps()) {
1133
bsalomon@google.com27847de2011-02-22 20:59:41 +00001134 fGpu = gpu;
1135 fGpu->ref();
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001136 fGpu->setContext(this);
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001137
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +00001138 fCustomPathRenderer = GrPathRenderer::CreatePathRenderer();
1139 fGpu->setClipPathRenderer(fCustomPathRenderer);
1140
bsalomon@google.com27847de2011-02-22 20:59:41 +00001141 fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT,
1142 MAX_TEXTURE_CACHE_BYTES);
1143 fFontCache = new GrFontCache(fGpu);
1144
1145 fLastDrawCategory = kUnbuffered_DrawCategory;
1146
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001147 fDrawBuffer = NULL;
1148 fDrawBufferVBAllocPool = NULL;
1149 fDrawBufferIBAllocPool = NULL;
1150
bsalomon@google.com205d4602011-04-25 12:43:45 +00001151 fAAFillRectIndexBuffer = NULL;
1152 fAAStrokeRectIndexBuffer = NULL;
1153
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001154 this->setupDrawBuffer();
1155}
1156
1157void GrContext::setupDrawBuffer() {
1158
1159 GrAssert(NULL == fDrawBuffer);
1160 GrAssert(NULL == fDrawBufferVBAllocPool);
1161 GrAssert(NULL == fDrawBufferIBAllocPool);
1162
bsalomon@google.com27847de2011-02-22 20:59:41 +00001163#if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +00001164 fDrawBufferVBAllocPool =
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001165 new GrVertexBufferAllocPool(fGpu, false,
bsalomon@google.com27847de2011-02-22 20:59:41 +00001166 DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
1167 DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +00001168 fDrawBufferIBAllocPool =
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001169 new GrIndexBufferAllocPool(fGpu, false,
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +00001170 DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
bsalomon@google.com27847de2011-02-22 20:59:41 +00001171 DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
1172
1173 fDrawBuffer = new GrInOrderDrawBuffer(fDrawBufferVBAllocPool,
1174 fDrawBufferIBAllocPool);
bsalomon@google.com27847de2011-02-22 20:59:41 +00001175#endif
1176
1177#if BATCH_RECT_TO_RECT
1178 fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
1179#endif
bsalomon@google.com27847de2011-02-22 20:59:41 +00001180}
1181
bsalomon@google.com27847de2011-02-22 20:59:41 +00001182GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
1183 GrDrawTarget* target;
1184#if DEFER_TEXT_RENDERING
1185 target = prepareToDraw(paint, kText_DrawCategory);
1186#else
1187 target = prepareToDraw(paint, kUnbuffered_DrawCategory);
1188#endif
1189 SetPaint(paint, target);
1190 return target;
1191}
1192
1193const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
1194 return fGpu->getQuadIndexBuffer();
1195}
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +00001196
1197GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
1198 GrPathIter* path,
1199 GrPathFill fill) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001200 if (NULL != fCustomPathRenderer &&
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +00001201 fCustomPathRenderer->canDrawPath(target, path, fill)) {
1202 return fCustomPathRenderer;
1203 } else {
1204 GrAssert(fDefaultPathRenderer.canDrawPath(target, path, fill));
1205 return &fDefaultPathRenderer;
1206 }
1207}