blob: 7cf0cca7cbfb61ad8c733c79d763df6c7889fbcd [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
106GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,
107 const GrSamplerState& sampler) {
108 finalizeTextureKey(key, sampler);
109 return fTextureCache->findAndLock(*key);
110}
111
112static void stretchImage(void* dst,
113 int dstW,
114 int dstH,
115 void* src,
116 int srcW,
117 int srcH,
118 int bpp) {
119 GrFixed dx = (srcW << 16) / dstW;
120 GrFixed dy = (srcH << 16) / dstH;
121
122 GrFixed y = dy >> 1;
123
124 int dstXLimit = dstW*bpp;
125 for (int j = 0; j < dstH; ++j) {
126 GrFixed x = dx >> 1;
127 void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
128 void* dstRow = (uint8_t*)dst + j*dstW*bpp;
129 for (int i = 0; i < dstXLimit; i += bpp) {
130 memcpy((uint8_t*) dstRow + i,
131 (uint8_t*) srcRow + (x>>16)*bpp,
132 bpp);
133 x += dx;
134 }
135 y += dy;
136 }
137}
138
139GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
140 const GrSamplerState& sampler,
141 const GrGpu::TextureDesc& desc,
142 void* srcData, size_t rowBytes) {
143 GrAssert(key->width() == desc.fWidth);
144 GrAssert(key->height() == desc.fHeight);
145
146#if GR_DUMP_TEXTURE_UPLOAD
147 GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
148#endif
149
150 GrTextureEntry* entry = NULL;
151 bool special = finalizeTextureKey(key, sampler);
152 if (special) {
153 GrTextureEntry* clampEntry;
154 GrTextureKey clampKey(*key);
155 clampEntry = findAndLockTexture(&clampKey, GrSamplerState::ClampNoFilter());
156
157 if (NULL == clampEntry) {
158 clampEntry = createAndLockTexture(&clampKey,
159 GrSamplerState::ClampNoFilter(),
160 desc, srcData, rowBytes);
161 GrAssert(NULL != clampEntry);
162 if (NULL == clampEntry) {
163 return NULL;
164 }
165 }
166 GrGpu::TextureDesc rtDesc = desc;
167 rtDesc.fFlags |= GrGpu::kRenderTarget_TextureFlag |
bsalomon@google.comf6a7c112011-03-24 16:14:10 +0000168 GrGpu::kNoStencil_TextureFlag;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000169 rtDesc.fWidth = GrNextPow2(GrMax<int>(desc.fWidth,
170 fGpu->minRenderTargetWidth()));
171 rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
172 fGpu->minRenderTargetHeight()));
173
174 GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
175
176 if (NULL != texture) {
177 GrDrawTarget::AutoStateRestore asr(fGpu);
178 fGpu->setRenderTarget(texture->asRenderTarget());
179 fGpu->setTexture(0, clampEntry->texture());
bsalomon@google.comd302f142011-03-03 13:54:13 +0000180 fGpu->disableStencil();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000181 fGpu->setViewMatrix(GrMatrix::I());
182 fGpu->setAlpha(0xff);
183 fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
184 fGpu->disableState(GrDrawTarget::kDither_StateBit |
185 GrDrawTarget::kClip_StateBit |
186 GrDrawTarget::kAntialias_StateBit);
187 GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,
188 GrSamplerState::kClamp_WrapMode,
189 sampler.isFilter());
190 fGpu->setSamplerState(0, stretchSampler);
191
192 static const GrVertexLayout layout =
193 GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
194 GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
195
196 if (arg.succeeded()) {
197 GrPoint* verts = (GrPoint*) arg.vertices();
198 verts[0].setIRectFan(0, 0,
199 texture->width(),
200 texture->height(),
201 2*sizeof(GrPoint));
202 verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
203 fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
204 0, 4);
205 entry = fTextureCache->createAndLock(*key, texture);
206 }
bsalomon@google.com1da07462011-03-10 14:51:57 +0000207 texture->releaseRenderTarget();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000208 } else {
209 // TODO: Our CPU stretch doesn't filter. But we create separate
210 // stretched textures when the sampler state is either filtered or
211 // not. Either implement filtered stretch blit on CPU or just create
212 // one when FBO case fails.
213
214 rtDesc.fFlags = 0;
215 // no longer need to clamp at min RT size.
216 rtDesc.fWidth = GrNextPow2(desc.fWidth);
217 rtDesc.fHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000218 int bpp = GrBytesPerPixel(desc.fFormat);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000219 GrAutoSMalloc<128*128*4> stretchedPixels(bpp *
220 rtDesc.fWidth *
221 rtDesc.fHeight);
222 stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
223 srcData, desc.fWidth, desc.fHeight, bpp);
224
225 size_t stretchedRowBytes = rtDesc.fWidth * bpp;
226
227 GrTexture* texture = fGpu->createTexture(rtDesc,
228 stretchedPixels.get(),
229 stretchedRowBytes);
230 GrAssert(NULL != texture);
231 entry = fTextureCache->createAndLock(*key, texture);
232 }
233 fTextureCache->unlock(clampEntry);
234
235 } else {
236 GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
237 if (NULL != texture) {
238 entry = fTextureCache->createAndLock(*key, texture);
239 } else {
240 entry = NULL;
241 }
242 }
243 return entry;
244}
245
246void GrContext::unlockTexture(GrTextureEntry* entry) {
247 fTextureCache->unlock(entry);
248}
249
250void GrContext::detachCachedTexture(GrTextureEntry* entry) {
251 fTextureCache->detach(entry);
252}
253
254void GrContext::reattachAndUnlockCachedTexture(GrTextureEntry* entry) {
255 fTextureCache->reattachAndUnlock(entry);
256}
257
258GrTexture* GrContext::createUncachedTexture(const GrGpu::TextureDesc& desc,
259 void* srcData,
260 size_t rowBytes) {
261 return fGpu->createTexture(desc, srcData, rowBytes);
262}
263
264void GrContext::getTextureCacheLimits(int* maxTextures,
265 size_t* maxTextureBytes) const {
266 fTextureCache->getLimits(maxTextures, maxTextureBytes);
267}
268
269void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
270 fTextureCache->setLimits(maxTextures, maxTextureBytes);
271}
272
273int GrContext::getMaxTextureDimension() {
274 return fGpu->maxTextureDimension();
275}
276
277///////////////////////////////////////////////////////////////////////////////
278
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000279GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
280 // validate flags here so that GrGpu subclasses don't have to check
281 if (kTexture_GrPlatformSurfaceType == desc.fSurfaceType &&
282 0 != desc.fRenderTargetFlags) {
283 return NULL;
284 }
285 if (!(kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) &&
286 (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
287 return NULL;
288 }
289 if (kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType &&
290 (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) &&
291 !(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
292 return NULL;
293 }
294 return fGpu->createPlatformSurface(desc);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000295}
296
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000297///////////////////////////////////////////////////////////////////////////////
298
bsalomon@google.com27847de2011-02-22 20:59:41 +0000299bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
300 int width, int height) {
301 if (!fGpu->supports8BitPalette()) {
302 return false;
303 }
304
305
306 bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
307
308 if (!isPow2) {
309 if (!fGpu->npotTextureSupport()) {
310 return false;
311 }
312
313 bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
314 sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
315 if (tiled && !fGpu->npotTextureTileSupport()) {
316 return false;
317 }
318 }
319 return true;
320}
321
322////////////////////////////////////////////////////////////////////////////////
323
324void GrContext::setClip(const GrClip& clip) {
325 fGpu->setClip(clip);
326 fGpu->enableState(GrDrawTarget::kClip_StateBit);
327}
328
329void GrContext::setClip(const GrIRect& rect) {
330 GrClip clip;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000331 clip.setFromIRect(rect);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000332 fGpu->setClip(clip);
333}
334
335////////////////////////////////////////////////////////////////////////////////
336
bsalomon@google.com398109c2011-04-14 18:40:27 +0000337void GrContext::clear(GrColor color) {
338 // gpu flush call is immediate, must flush.
339 // (could in theory skip draws to current render target.)
340 this->flush();
341 fGpu->clear(color);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000342}
343
344void GrContext::drawPaint(const GrPaint& paint) {
345 // set rect to be big enough to fill the space, but not super-huge, so we
346 // don't overflow fixed-point implementations
bsalomon@google.comd302f142011-03-03 13:54:13 +0000347 GrRect r;
348 r.setLTRB(0, 0,
349 GrIntToScalar(getRenderTarget()->width()),
350 GrIntToScalar(getRenderTarget()->height()));
bsalomon@google.com27847de2011-02-22 20:59:41 +0000351 GrMatrix inverse;
352 if (fGpu->getViewInverse(&inverse)) {
353 inverse.mapRect(&r);
354 } else {
355 GrPrintf("---- fGpu->getViewInverse failed\n");
356 }
357 this->drawRect(paint, r);
358}
359
bsalomon@google.com205d4602011-04-25 12:43:45 +0000360////////////////////////////////////////////////////////////////////////////////
361
bsalomon@google.com27847de2011-02-22 20:59:41 +0000362/* create a triangle strip that strokes the specified triangle. There are 8
363 unique vertices, but we repreat the last 2 to close up. Alternatively we
364 could use an indices array, and then only send 8 verts, but not sure that
365 would be faster.
366 */
bsalomon@google.com205d4602011-04-25 12:43:45 +0000367static void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
bsalomon@google.com27847de2011-02-22 20:59:41 +0000368 GrScalar width) {
369 const GrScalar rad = GrScalarHalf(width);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000370 rect.sort();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000371
372 verts[0].set(rect.fLeft + rad, rect.fTop + rad);
373 verts[1].set(rect.fLeft - rad, rect.fTop - rad);
374 verts[2].set(rect.fRight - rad, rect.fTop + rad);
375 verts[3].set(rect.fRight + rad, rect.fTop - rad);
376 verts[4].set(rect.fRight - rad, rect.fBottom - rad);
377 verts[5].set(rect.fRight + rad, rect.fBottom + rad);
378 verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
379 verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
380 verts[8] = verts[0];
381 verts[9] = verts[1];
382}
383
bsalomon@google.com205d4602011-04-25 12:43:45 +0000384static GrColor getColorForMesh(const GrPaint& paint) {
385 if (NULL == paint.getTexture()) {
386 return paint.fColor;
387 } else {
388 unsigned a = GrColorUnpackA(paint.fColor);
389 return GrColorPackRGBA(a, a, a, a);
390 }
391}
392
393static void setInsetFan(GrPoint* pts, size_t stride,
394 const GrRect& r, GrScalar dx, GrScalar dy) {
395 pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride);
396}
397
398static const uint16_t gFillAARectIdx[] = {
399 0, 1, 5, 5, 4, 0,
400 1, 2, 6, 6, 5, 1,
401 2, 3, 7, 7, 6, 2,
402 3, 0, 4, 4, 7, 3,
403 4, 5, 6, 6, 7, 4,
404};
405
406int GrContext::aaFillRectIndexCount() const {
407 return GR_ARRAY_COUNT(gFillAARectIdx);
408}
409
410GrIndexBuffer* GrContext::aaFillRectIndexBuffer() {
411 if (NULL == fAAFillRectIndexBuffer) {
412 fAAFillRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gFillAARectIdx),
413 false);
414 GrAssert(NULL != fAAFillRectIndexBuffer);
415#if GR_DEBUG
416 bool updated =
417#endif
418 fAAFillRectIndexBuffer->updateData(gFillAARectIdx,
419 sizeof(gFillAARectIdx));
420 GR_DEBUGASSERT(updated);
421 }
422 return fAAFillRectIndexBuffer;
423}
424
425static const uint16_t gStrokeAARectIdx[] = {
426 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
427 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
428 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
429 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
430
431 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
432 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
433 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
434 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
435
436 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
437 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
438 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
439 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
440};
441
442int GrContext::aaStrokeRectIndexCount() const {
443 return GR_ARRAY_COUNT(gStrokeAARectIdx);
444}
445
446GrIndexBuffer* GrContext::aaStrokeRectIndexBuffer() {
447 if (NULL == fAAStrokeRectIndexBuffer) {
448 fAAStrokeRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gStrokeAARectIdx),
449 false);
450 GrAssert(NULL != fAAStrokeRectIndexBuffer);
451#if GR_DEBUG
452 bool updated =
453#endif
454 fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
455 sizeof(gStrokeAARectIdx));
456 GR_DEBUGASSERT(updated);
457 }
458 return fAAStrokeRectIndexBuffer;
459}
460
461void GrContext::fillAARect(GrDrawTarget* target,
462 const GrPaint& paint,
463 const GrRect& devRect) {
464
465 GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit;
466 if (NULL != paint.getTexture()) {
467 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
468 }
469
470 size_t vsize = GrDrawTarget::VertexSize(layout);
471
472 GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0);
473
474 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
475
476 GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
477 GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
478
479 setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf);
480 setInsetFan(fan1Pos, vsize, devRect, GR_ScalarHalf, GR_ScalarHalf);
481
482 verts += sizeof(GrPoint);
483 for (int i = 0; i < 4; ++i) {
484 *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
485 }
486
487 GrColor innerColor = getColorForMesh(paint);
488 verts += 4 * vsize;
489 for (int i = 0; i < 4; ++i) {
490 *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
491 }
492
493 target->setIndexSourceToBuffer(this->aaFillRectIndexBuffer());
494
495 target->drawIndexed(kTriangles_PrimitiveType, 0,
496 0, 8, this->aaFillRectIndexCount());
497}
498
499void GrContext::strokeAARect(GrDrawTarget* target, const GrPaint& paint,
500 const GrRect& devRect, const GrVec& devStrokeSize) {
501 const GrScalar& dx = devStrokeSize.fX;
502 const GrScalar& dy = devStrokeSize.fY;
503 const GrScalar rx = GrMul(dx, GR_ScalarHalf);
504 const GrScalar ry = GrMul(dy, GR_ScalarHalf);
505
506 GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit;
507
508 if (NULL != paint.getTexture()) {
509 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
510 }
511
512 GrScalar spare;
513 {
514 GrScalar w = devRect.width() - dx;
515 GrScalar h = devRect.height() - dy;
516 spare = GrMin(w, h);
517 }
518
519 if (spare <= 0) {
520 GrRect r(devRect);
521 r.inset(-rx, -ry);
522 fillAARect(target, paint, r);
523 return;
524 }
525
526 size_t vsize = GrDrawTarget::VertexSize(layout);
527
528 GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 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 GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
535 GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
536
537 setInsetFan(fan0Pos, vsize, devRect, -rx - GR_ScalarHalf, -ry - GR_ScalarHalf);
538 setInsetFan(fan1Pos, vsize, devRect, -rx + GR_ScalarHalf, -ry + GR_ScalarHalf);
539 setInsetFan(fan2Pos, vsize, devRect, rx - GR_ScalarHalf, ry - GR_ScalarHalf);
540 setInsetFan(fan3Pos, vsize, devRect, rx + GR_ScalarHalf, ry + GR_ScalarHalf);
541
542 verts += sizeof(GrPoint);
543 for (int i = 0; i < 4; ++i) {
544 *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
545 }
546
547 GrColor innerColor = getColorForMesh(paint);
548 verts += 4 * vsize;
549 for (int i = 0; i < 8; ++i) {
550 *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
551 }
552
553 verts += 8 * vsize;
554 for (int i = 0; i < 8; ++i) {
555 *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
556 }
557
558 target->setIndexSourceToBuffer(aaStrokeRectIndexBuffer());
559 target->drawIndexed(kTriangles_PrimitiveType,
560 0, 0, 16, aaStrokeRectIndexCount());
561}
562
563static bool apply_aa_to_rect(GrDrawTarget* target,
564 GrGpu* gpu,
565 const GrPaint& paint,
566 const GrRect& rect,
567 GrScalar width,
568 const GrMatrix* matrix,
569 GrMatrix* combinedMatrix,
570 GrRect* devRect) {
571 // we use a simple alpha ramp to do aa on axis-aligned rects
572 // do AA with alpha ramp if the caller requested AA, the rect
573 // will be axis-aligned,the render target is not
574 // multisampled, and the rect won't land on integer coords.
575
576 if (!paint.fAntiAlias) {
577 return false;
578 }
579
580 if (target->getRenderTarget()->isMultisampled()) {
581 return false;
582 }
583
584 if (0 == width && gpu->supportsAALines()) {
585 return false;
586 }
587
588 if (!target->getViewMatrix().preservesAxisAlignment()) {
589 return false;
590 }
591
592 if (NULL != matrix &&
593 !matrix->preservesAxisAlignment()) {
594 return false;
595 }
596
597 *combinedMatrix = target->getViewMatrix();
598 if (NULL != matrix) {
599 combinedMatrix->preConcat(*matrix);
600 GrAssert(combinedMatrix->preservesAxisAlignment());
601 }
602
603 combinedMatrix->mapRect(devRect, rect);
604 devRect->sort();
605
606 if (width < 0) {
607 return !devRect->isIRect();
608 } else {
609 return true;
610 }
611}
612
bsalomon@google.com27847de2011-02-22 20:59:41 +0000613void GrContext::drawRect(const GrPaint& paint,
614 const GrRect& rect,
615 GrScalar width,
616 const GrMatrix* matrix) {
617
618 bool textured = NULL != paint.getTexture();
619
620 GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
621
bsalomon@google.com205d4602011-04-25 12:43:45 +0000622 GrRect devRect = rect;
623 GrMatrix combinedMatrix;
624 bool doAA = apply_aa_to_rect(target, fGpu, paint, rect, width, matrix,
625 &combinedMatrix, &devRect);
626
627 if (doAA) {
628 GrDrawTarget::AutoViewMatrixRestore avm(target);
629 if (textured) {
630 GrMatrix inv;
631 if (combinedMatrix.invert(&inv)) {
632 target->preConcatSamplerMatrix(0, inv);
633 }
634 }
635 target->setViewMatrix(GrMatrix::I());
636 if (width >= 0) {
637 GrVec strokeSize;;
638 if (width > 0) {
639 strokeSize.set(width, width);
640 combinedMatrix.mapVec(&strokeSize);
641 strokeSize.setAbs(strokeSize);
642 } else {
643 strokeSize.set(GR_Scalar1, GR_Scalar1);
644 }
645 strokeAARect(target, paint, devRect, strokeSize);
646 } else {
647 fillAARect(target, paint, devRect);
648 }
649 return;
650 }
651
bsalomon@google.com27847de2011-02-22 20:59:41 +0000652 if (width >= 0) {
653 // TODO: consider making static vertex buffers for these cases.
654 // Hairline could be done by just adding closing vertex to
655 // unitSquareVertexBuffer()
bsalomon@google.com205d4602011-04-25 12:43:45 +0000656 GrVertexLayout layout = textured ?
657 GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
658 0;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000659 static const int worstCaseVertCount = 10;
660 GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
661
662 if (!geo.succeeded()) {
663 return;
664 }
665
666 GrPrimitiveType primType;
667 int vertCount;
668 GrPoint* vertex = geo.positions();
669
670 if (width > 0) {
671 vertCount = 10;
672 primType = kTriangleStrip_PrimitiveType;
673 setStrokeRectStrip(vertex, rect, width);
674 } else {
675 // hairline
676 vertCount = 5;
677 primType = kLineStrip_PrimitiveType;
678 vertex[0].set(rect.fLeft, rect.fTop);
679 vertex[1].set(rect.fRight, rect.fTop);
680 vertex[2].set(rect.fRight, rect.fBottom);
681 vertex[3].set(rect.fLeft, rect.fBottom);
682 vertex[4].set(rect.fLeft, rect.fTop);
683 }
684
685 GrDrawTarget::AutoViewMatrixRestore avmr;
686 if (NULL != matrix) {
687 avmr.set(target);
688 target->preConcatViewMatrix(*matrix);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000689 if (textured) {
690 target->preConcatSamplerMatrix(0, *matrix);
691 }
bsalomon@google.com27847de2011-02-22 20:59:41 +0000692 }
693
694 target->drawNonIndexed(primType, 0, vertCount);
695 } else {
696 #if GR_STATIC_RECT_VB
697 GrVertexLayout layout = (textured) ?
698 GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
699 0;
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +0000700 target->setVertexSourceToBuffer(layout,
bsalomon@google.com27847de2011-02-22 20:59:41 +0000701 fGpu->getUnitSquareVertexBuffer());
702 GrDrawTarget::AutoViewMatrixRestore avmr(target);
703 GrMatrix m;
704 m.setAll(rect.width(), 0, rect.fLeft,
bsalomon@google.com205d4602011-04-25 12:43:45 +0000705 0, rect.height(), rect.fTop,
706 0, 0, GrMatrix::I()[8]);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000707
708 if (NULL != matrix) {
709 m.postConcat(*matrix);
710 }
711
712 target->preConcatViewMatrix(m);
713
714 if (textured) {
715 target->preConcatSamplerMatrix(0, m);
716 }
717 target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
718 #else
719 target->drawSimpleRect(rect, matrix, textured ? 1 : 0);
720 #endif
721 }
722}
723
724void GrContext::drawRectToRect(const GrPaint& paint,
725 const GrRect& dstRect,
726 const GrRect& srcRect,
727 const GrMatrix* dstMatrix,
728 const GrMatrix* srcMatrix) {
729
730 if (NULL == paint.getTexture()) {
731 drawRect(paint, dstRect, -1, dstMatrix);
732 return;
733 }
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +0000734
bsalomon@google.com27847de2011-02-22 20:59:41 +0000735 GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
736
737#if GR_STATIC_RECT_VB
738 GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
739
740 GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
741 GrDrawTarget::AutoViewMatrixRestore avmr(target);
742
743 GrMatrix m;
744
745 m.setAll(dstRect.width(), 0, dstRect.fLeft,
746 0, dstRect.height(), dstRect.fTop,
747 0, 0, GrMatrix::I()[8]);
748 if (NULL != dstMatrix) {
749 m.postConcat(*dstMatrix);
750 }
751 target->preConcatViewMatrix(m);
752
753 m.setAll(srcRect.width(), 0, srcRect.fLeft,
754 0, srcRect.height(), srcRect.fTop,
755 0, 0, GrMatrix::I()[8]);
756 if (NULL != srcMatrix) {
757 m.postConcat(*srcMatrix);
758 }
759 target->preConcatSamplerMatrix(0, m);
760
761 target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());
762 target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
763#else
764
765 GrDrawTarget* target;
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +0000766#if BATCH_RECT_TO_RECT
bsalomon@google.com27847de2011-02-22 20:59:41 +0000767 target = this->prepareToDraw(paint, kBuffered_DrawCategory);
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +0000768#else
bsalomon@google.com27847de2011-02-22 20:59:41 +0000769 target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
770#endif
771
772 const GrRect* srcRects[GrDrawTarget::kNumStages] = {NULL};
773 const GrMatrix* srcMatrices[GrDrawTarget::kNumStages] = {NULL};
774 srcRects[0] = &srcRect;
775 srcMatrices[0] = srcMatrix;
776
777 target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
778#endif
779}
780
781void GrContext::drawVertices(const GrPaint& paint,
782 GrPrimitiveType primitiveType,
783 int vertexCount,
784 const GrPoint positions[],
785 const GrPoint texCoords[],
786 const GrColor colors[],
787 const uint16_t indices[],
788 int indexCount) {
789 GrVertexLayout layout = 0;
790 int vertexSize = sizeof(GrPoint);
791
792 GrDrawTarget::AutoReleaseGeometry geo;
793
794 GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
795
796 if (NULL != paint.getTexture()) {
797 if (NULL == texCoords) {
798 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
799 } else {
800 layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
801 vertexSize += sizeof(GrPoint);
802 }
803 }
804
805 if (NULL != colors) {
806 layout |= GrDrawTarget::kColor_VertexLayoutBit;
807 vertexSize += sizeof(GrColor);
808 }
809
810 if (sizeof(GrPoint) != vertexSize) {
811 if (!geo.set(target, layout, vertexCount, 0)) {
812 GrPrintf("Failed to get space for vertices!");
813 return;
814 }
815 int texOffsets[GrDrawTarget::kMaxTexCoords];
816 int colorOffset;
817 int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
818 texOffsets,
819 &colorOffset);
820 void* curVertex = geo.vertices();
821
822 for (int i = 0; i < vertexCount; ++i) {
823 *((GrPoint*)curVertex) = positions[i];
824
825 if (texOffsets[0] > 0) {
826 *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
827 }
828 if (colorOffset > 0) {
829 *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
830 }
831 curVertex = (void*)((intptr_t)curVertex + vsize);
832 }
833 } else {
834 target->setVertexSourceToArray(layout, positions, vertexCount);
835 }
836
837 if (NULL != indices) {
838 target->setIndexSourceToArray(indices, indexCount);
839 target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
840 } else {
841 target->drawNonIndexed(primitiveType, 0, vertexCount);
842 }
843}
844
845
846////////////////////////////////////////////////////////////////////////////////
847
848void GrContext::drawPath(const GrPaint& paint,
849 GrPathIter* path,
850 GrPathFill fill,
851 const GrPoint* translate) {
852
853
854 GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
855
856 GrDrawTarget::StageBitfield enabledStages = 0;
857 if (NULL != paint.getTexture()) {
858 enabledStages |= 1;
859 }
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000860 GrPathRenderer* pr = getPathRenderer(target, path, fill);
861 pr->drawPath(target, enabledStages, path, fill, translate);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000862}
863
bsalomon@google.comd302f142011-03-03 13:54:13 +0000864void GrContext::drawPath(const GrPaint& paint,
865 const GrPath& path,
866 GrPathFill fill,
867 const GrPoint* translate) {
868 GrPath::Iter iter(path);
869 this->drawPath(paint, &iter, fill, translate);
870}
871
872
bsalomon@google.com27847de2011-02-22 20:59:41 +0000873////////////////////////////////////////////////////////////////////////////////
874
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000875void GrContext::flush(int flagsBitfield) {
876 if (kDiscard_FlushBit & flagsBitfield) {
877 fDrawBuffer->reset();
878 } else {
879 flushDrawBuffer();
880 }
881
882 if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
bsalomon@google.com27847de2011-02-22 20:59:41 +0000883 fGpu->forceRenderTargetFlush();
884 }
885}
886
887void GrContext::flushText() {
888 if (kText_DrawCategory == fLastDrawCategory) {
889 flushDrawBuffer();
890 }
891}
892
893void GrContext::flushDrawBuffer() {
894#if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
895 fDrawBuffer->playback(fGpu);
896 fDrawBuffer->reset();
897#endif
898}
899
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000900bool GrContext::readTexturePixels(GrTexture* texture,
901 int left, int top, int width, int height,
902 GrPixelConfig config, void* buffer) {
903
904 // TODO: code read pixels for textures that aren't rendertargets
905
906 this->flush();
907 GrRenderTarget* target = texture->asRenderTarget();
908 if (NULL != target) {
909 return fGpu->readPixels(target,
910 left, top, width, height,
911 config, buffer);
912 } else {
913 return false;
914 }
915}
916
917bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
918 int left, int top, int width, int height,
919 GrPixelConfig config, void* buffer) {
920 uint32_t flushFlags = 0;
921 if (NULL == target) {
922 flushFlags |= GrContext::kForceCurrentRenderTarget_FlushBit;
923 }
924
925 this->flush(flushFlags);
926 return fGpu->readPixels(target,
927 left, top, width, height,
928 config, buffer);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000929}
930
931void GrContext::writePixels(int left, int top, int width, int height,
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000932 GrPixelConfig config, const void* buffer,
bsalomon@google.com27847de2011-02-22 20:59:41 +0000933 size_t stride) {
934
935 // TODO: when underlying api has a direct way to do this we should use it
936 // (e.g. glDrawPixels on desktop GL).
937
938 const GrGpu::TextureDesc desc = {
939 0, GrGpu::kNone_AALevel, width, height, config
940 };
941 GrTexture* texture = fGpu->createTexture(desc, buffer, stride);
942 if (NULL == texture) {
943 return;
944 }
945
946 this->flush(true);
947
948 GrAutoUnref aur(texture);
949 GrDrawTarget::AutoStateRestore asr(fGpu);
950
951 GrMatrix matrix;
952 matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
953 fGpu->setViewMatrix(matrix);
954
955 fGpu->disableState(GrDrawTarget::kClip_StateBit);
956 fGpu->setAlpha(0xFF);
957 fGpu->setBlendFunc(kOne_BlendCoeff,
958 kZero_BlendCoeff);
959 fGpu->setTexture(0, texture);
960
961 GrSamplerState sampler;
962 sampler.setClampNoFilter();
963 matrix.setScale(GR_Scalar1 / width, GR_Scalar1 / height);
964 sampler.setMatrix(matrix);
965 fGpu->setSamplerState(0, sampler);
966
967 GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
968 static const int VCOUNT = 4;
969
970 GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
971 if (!geo.succeeded()) {
972 return;
973 }
974 ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
975 fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);
976}
977////////////////////////////////////////////////////////////////////////////////
978
979void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
980 target->setTexture(0, paint.getTexture());
981 target->setSamplerState(0, paint.fSampler);
982 target->setColor(paint.fColor);
983
984 if (paint.fDither) {
985 target->enableState(GrDrawTarget::kDither_StateBit);
986 } else {
987 target->disableState(GrDrawTarget::kDither_StateBit);
988 }
989 if (paint.fAntiAlias) {
990 target->enableState(GrDrawTarget::kAntialias_StateBit);
991 } else {
992 target->disableState(GrDrawTarget::kAntialias_StateBit);
993 }
994 target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
995}
996
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +0000997GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
bsalomon@google.com27847de2011-02-22 20:59:41 +0000998 DrawCategory category) {
999 if (category != fLastDrawCategory) {
1000 flushDrawBuffer();
1001 fLastDrawCategory = category;
1002 }
1003 SetPaint(paint, fGpu);
1004 GrDrawTarget* target = fGpu;
1005 switch (category) {
1006 case kText_DrawCategory:
1007#if DEFER_TEXT_RENDERING
1008 target = fDrawBuffer;
1009 fDrawBuffer->initializeDrawStateAndClip(*fGpu);
1010#else
1011 target = fGpu;
1012#endif
1013 break;
1014 case kUnbuffered_DrawCategory:
1015 target = fGpu;
1016 break;
1017 case kBuffered_DrawCategory:
1018 target = fDrawBuffer;
1019 fDrawBuffer->initializeDrawStateAndClip(*fGpu);
1020 break;
1021 }
1022 return target;
1023}
1024
1025////////////////////////////////////////////////////////////////////////////////
1026
bsalomon@google.com27847de2011-02-22 20:59:41 +00001027void GrContext::setRenderTarget(GrRenderTarget* target) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001028 this->flush(false);
bsalomon@google.com27847de2011-02-22 20:59:41 +00001029 fGpu->setRenderTarget(target);
1030}
1031
1032GrRenderTarget* GrContext::getRenderTarget() {
1033 return fGpu->getRenderTarget();
1034}
1035
1036const GrRenderTarget* GrContext::getRenderTarget() const {
1037 return fGpu->getRenderTarget();
1038}
1039
1040const GrMatrix& GrContext::getMatrix() const {
1041 return fGpu->getViewMatrix();
1042}
1043
1044void GrContext::setMatrix(const GrMatrix& m) {
1045 fGpu->setViewMatrix(m);
1046}
1047
1048void GrContext::concatMatrix(const GrMatrix& m) const {
1049 fGpu->preConcatViewMatrix(m);
1050}
1051
1052static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
1053 intptr_t mask = 1 << shift;
1054 if (pred) {
1055 bits |= mask;
1056 } else {
1057 bits &= ~mask;
1058 }
1059 return bits;
1060}
1061
1062void GrContext::resetStats() {
1063 fGpu->resetStats();
1064}
1065
1066const GrGpu::Stats& GrContext::getStats() const {
1067 return fGpu->getStats();
1068}
1069
1070void GrContext::printStats() const {
1071 fGpu->printStats();
1072}
1073
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +00001074GrContext::GrContext(GrGpu* gpu) :
1075 fDefaultPathRenderer(gpu->supportsTwoSidedStencil(),
1076 gpu->supportsStencilWrapOps()) {
1077
bsalomon@google.com27847de2011-02-22 20:59:41 +00001078 fGpu = gpu;
1079 fGpu->ref();
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001080 fGpu->setContext(this);
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001081
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +00001082 fCustomPathRenderer = GrPathRenderer::CreatePathRenderer();
1083 fGpu->setClipPathRenderer(fCustomPathRenderer);
1084
bsalomon@google.com27847de2011-02-22 20:59:41 +00001085 fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT,
1086 MAX_TEXTURE_CACHE_BYTES);
1087 fFontCache = new GrFontCache(fGpu);
1088
1089 fLastDrawCategory = kUnbuffered_DrawCategory;
1090
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001091 fDrawBuffer = NULL;
1092 fDrawBufferVBAllocPool = NULL;
1093 fDrawBufferIBAllocPool = NULL;
1094
bsalomon@google.com205d4602011-04-25 12:43:45 +00001095 fAAFillRectIndexBuffer = NULL;
1096 fAAStrokeRectIndexBuffer = NULL;
1097
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001098 this->setupDrawBuffer();
1099}
1100
1101void GrContext::setupDrawBuffer() {
1102
1103 GrAssert(NULL == fDrawBuffer);
1104 GrAssert(NULL == fDrawBufferVBAllocPool);
1105 GrAssert(NULL == fDrawBufferIBAllocPool);
1106
bsalomon@google.com27847de2011-02-22 20:59:41 +00001107#if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +00001108 fDrawBufferVBAllocPool =
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001109 new GrVertexBufferAllocPool(fGpu, false,
bsalomon@google.com27847de2011-02-22 20:59:41 +00001110 DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
1111 DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +00001112 fDrawBufferIBAllocPool =
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001113 new GrIndexBufferAllocPool(fGpu, false,
bsalomon@google.comde6ac2d2011-02-25 21:50:42 +00001114 DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
bsalomon@google.com27847de2011-02-22 20:59:41 +00001115 DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
1116
1117 fDrawBuffer = new GrInOrderDrawBuffer(fDrawBufferVBAllocPool,
1118 fDrawBufferIBAllocPool);
bsalomon@google.com27847de2011-02-22 20:59:41 +00001119#endif
1120
1121#if BATCH_RECT_TO_RECT
1122 fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
1123#endif
bsalomon@google.com27847de2011-02-22 20:59:41 +00001124}
1125
1126bool GrContext::finalizeTextureKey(GrTextureKey* key,
1127 const GrSamplerState& sampler) const {
1128 uint32_t bits = 0;
1129 uint16_t width = key->width();
1130 uint16_t height = key->height();
1131
1132
1133 if (!fGpu->npotTextureTileSupport()) {
1134 bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
1135
1136 bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
1137 (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
1138
1139 if (tiled && !isPow2) {
1140 bits |= 1;
1141 bits |= sampler.isFilter() ? 2 : 0;
1142 }
1143 }
1144 key->finalize(bits);
1145 return 0 != bits;
1146}
1147
1148GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
1149 GrDrawTarget* target;
1150#if DEFER_TEXT_RENDERING
1151 target = prepareToDraw(paint, kText_DrawCategory);
1152#else
1153 target = prepareToDraw(paint, kUnbuffered_DrawCategory);
1154#endif
1155 SetPaint(paint, target);
1156 return target;
1157}
1158
1159const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
1160 return fGpu->getQuadIndexBuffer();
1161}
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +00001162
1163GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
1164 GrPathIter* path,
1165 GrPathFill fill) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001166 if (NULL != fCustomPathRenderer &&
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +00001167 fCustomPathRenderer->canDrawPath(target, path, fill)) {
1168 return fCustomPathRenderer;
1169 } else {
1170 GrAssert(fDefaultPathRenderer.canDrawPath(target, path, fill));
1171 return &fDefaultPathRenderer;
1172 }
1173}