blob: f966c2c9d6e30f8036907b7c9fdd3d19b5fe65b5 [file] [log] [blame]
reed@google.com873cb1e2010-12-23 15:00:45 +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
18#include "GrContext.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
26#define DEFER_TEXT_RENDERING 1
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000027#define USE_STATIC_RECT_VB 0
reed@google.comac10a2d2010-12-22 21:39:39 +000028
29static const size_t MAX_TEXTURE_CACHE_COUNT = 128;
30static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024;
31
32#if DEFER_TEXT_RENDERING
33 static const uint32_t POOL_VB_SIZE = 2048 *
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +000034 GrDrawTarget::VertexSize(
35 GrDrawTarget::kTextFormat_VertexLayoutBit |
bsalomon@google.com1572b072011-01-18 15:30:57 +000036 GrDrawTarget::StageTexCoordVertexLayoutBit(0,0));
reed@google.comac10a2d2010-12-22 21:39:39 +000037 static const uint32_t NUM_POOL_VBS = 8;
38#else
39 static const uint32_t POOL_VB_SIZE = 0;
40 static const uint32_t NUM_POOL_VBS = 0;
41
42#endif
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
reed@google.com873cb1e2010-12-23 15:00:45 +000055GrContext* GrContext::CreateGLShaderContext() {
56 return GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);
57}
58
reed@google.comac10a2d2010-12-22 21:39:39 +000059GrContext::~GrContext() {
60 fGpu->unref();
61 delete fTextureCache;
62 delete fFontCache;
63}
64
65void GrContext::abandonAllTextures() {
66 fTextureCache->deleteAll(GrTextureCache::kAbandonTexture_DeleteMode);
67 fFontCache->abandonAll();
68}
69
70GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,
71 const GrSamplerState& sampler) {
72 finalizeTextureKey(key, sampler);
73 return fTextureCache->findAndLock(*key);
74}
75
76static void stretchImage(void* dst,
77 int dstW,
78 int dstH,
79 void* src,
80 int srcW,
81 int srcH,
82 int bpp) {
83 GrFixed dx = (srcW << 16) / dstW;
84 GrFixed dy = (srcH << 16) / dstH;
85
86 GrFixed y = dy >> 1;
87
88 int dstXLimit = dstW*bpp;
89 for (int j = 0; j < dstH; ++j) {
90 GrFixed x = dx >> 1;
91 void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
92 void* dstRow = (uint8_t*)dst + j*dstW*bpp;
93 for (int i = 0; i < dstXLimit; i += bpp) {
94 memcpy((uint8_t*) dstRow + i,
95 (uint8_t*) srcRow + (x>>16)*bpp,
96 bpp);
97 x += dx;
98 }
99 y += dy;
100 }
101}
102
103GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
104 const GrSamplerState& sampler,
105 const GrGpu::TextureDesc& desc,
106 void* srcData, size_t rowBytes) {
107 GrAssert(key->width() == desc.fWidth);
108 GrAssert(key->height() == desc.fHeight);
109
110#if GR_DUMP_TEXTURE_UPLOAD
111 GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
112#endif
113
114 GrTextureEntry* entry = NULL;
115 bool special = finalizeTextureKey(key, sampler);
116 if (special) {
117 GrTextureEntry* clampEntry;
118 GrTextureKey clampKey(*key);
119 clampEntry = findAndLockTexture(&clampKey, GrSamplerState::ClampNoFilter());
120
121 if (NULL == clampEntry) {
122 clampEntry = createAndLockTexture(&clampKey,
123 GrSamplerState::ClampNoFilter(),
124 desc, srcData, rowBytes);
125 GrAssert(NULL != clampEntry);
126 if (NULL == clampEntry) {
127 return NULL;
128 }
129 }
130 GrTexture* clampTexture = clampEntry->texture();
131 GrGpu::TextureDesc rtDesc = desc;
132 rtDesc.fFlags |= GrGpu::kRenderTarget_TextureFlag |
133 GrGpu::kNoPathRendering_TextureFlag;
134 rtDesc.fWidth = GrNextPow2(GrMax<int>(desc.fWidth,
135 fGpu->minRenderTargetWidth()));
136 rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
137 fGpu->minRenderTargetHeight()));
138
139 GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
140
141 if (NULL != texture) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000142 GrDrawTarget::AutoStateRestore asr(fGpu);
reed@google.comac10a2d2010-12-22 21:39:39 +0000143 fGpu->setRenderTarget(texture->asRenderTarget());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000144 fGpu->setTexture(0, clampEntry->texture());
bsalomon@google.com5782d712011-01-21 21:03:59 +0000145 fGpu->setStencilPass(GrDrawTarget::kNone_StencilPass);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000146 fGpu->setTextureMatrix(0, GrMatrix::I());
reed@google.comac10a2d2010-12-22 21:39:39 +0000147 fGpu->setViewMatrix(GrMatrix::I());
148 fGpu->setAlpha(0xff);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000149 fGpu->setBlendFunc(GrDrawTarget::kOne_BlendCoeff, GrDrawTarget::kZero_BlendCoeff);
150 fGpu->disableState(GrDrawTarget::kDither_StateBit |
151 GrDrawTarget::kClip_StateBit |
152 GrDrawTarget::kAntialias_StateBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,
154 GrSamplerState::kClamp_WrapMode,
155 sampler.isFilter());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000156 fGpu->setSamplerState(0, stretchSampler);
reed@google.comac10a2d2010-12-22 21:39:39 +0000157
158 static const GrVertexLayout layout =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000159 GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000160 GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
161
162 if (arg.succeeded()) {
163 GrPoint* verts = (GrPoint*) arg.vertices();
164 verts[0].setIRectFan(0, 0,
165 texture->contentWidth(),
166 texture->contentHeight(),
167 2*sizeof(GrPoint));
168 GrScalar tw = GrFixedToScalar(GR_Fixed1 *
169 clampTexture->contentWidth() /
170 clampTexture->allocWidth());
171 GrScalar th = GrFixedToScalar(GR_Fixed1 *
172 clampTexture->contentHeight() /
173 clampTexture->allocHeight());
174 verts[1].setRectFan(0, 0, tw, th, 2*sizeof(GrPoint));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000175 fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +0000176 0, 4);
177 entry = fTextureCache->createAndLock(*key, texture);
178 }
179 texture->removeRenderTarget();
180 } else {
181 // TODO: Our CPU stretch doesn't filter. But we create separate
182 // stretched textures when the sampler state is either filtered or
183 // not. Either implement filtered stretch blit on CPU or just create
184 // one when FBO case fails.
185
186 rtDesc.fFlags = 0;
187 // no longer need to clamp at min RT size.
188 rtDesc.fWidth = GrNextPow2(desc.fWidth);
189 rtDesc.fHeight = GrNextPow2(desc.fHeight);
190 int bpp = GrTexture::BytesPerPixel(desc.fFormat);
191 GrAutoSMalloc<128*128*4> stretchedPixels(bpp *
192 rtDesc.fWidth *
193 rtDesc.fHeight);
194 stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
195 srcData, desc.fWidth, desc.fHeight, bpp);
196
197 size_t stretchedRowBytes = rtDesc.fWidth * bpp;
198
199 GrTexture* texture = fGpu->createTexture(rtDesc,
200 stretchedPixels.get(),
201 stretchedRowBytes);
202 GrAssert(NULL != texture);
203 entry = fTextureCache->createAndLock(*key, texture);
204 }
205 fTextureCache->unlock(clampEntry);
206
207 } else {
208 GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
209 if (NULL != texture) {
210 entry = fTextureCache->createAndLock(*key, texture);
211 } else {
212 entry = NULL;
213 }
214 }
215 return entry;
216}
217
218void GrContext::unlockTexture(GrTextureEntry* entry) {
219 fTextureCache->unlock(entry);
220}
221
222void GrContext::detachCachedTexture(GrTextureEntry* entry) {
223 fTextureCache->detach(entry);
224}
225
226void GrContext::reattachAndUnlockCachedTexture(GrTextureEntry* entry) {
227 fTextureCache->reattachAndUnlock(entry);
228}
229
230GrTexture* GrContext::createUncachedTexture(const GrGpu::TextureDesc& desc,
231 void* srcData,
232 size_t rowBytes) {
233 return fGpu->createTexture(desc, srcData, rowBytes);
234}
235
reed@google.com01804b42011-01-18 21:50:41 +0000236void GrContext::getTextureCacheLimits(int* maxTextures,
237 size_t* maxTextureBytes) const {
238 fTextureCache->getLimits(maxTextures, maxTextureBytes);
239}
240
241void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
242 fTextureCache->setLimits(maxTextures, maxTextureBytes);
243}
244
reed@google.com02a7e6c2011-01-28 21:21:49 +0000245int GrContext::getMaxTextureDimension() {
246 return fGpu->maxTextureDimension();
247}
248
reed@google.com01804b42011-01-18 21:50:41 +0000249///////////////////////////////////////////////////////////////////////////////
250
reed@google.comac10a2d2010-12-22 21:39:39 +0000251GrRenderTarget* GrContext::createPlatformRenderTarget(intptr_t platformRenderTarget,
252 int width, int height) {
253 return fGpu->createPlatformRenderTarget(platformRenderTarget,
254 width, height);
255}
256
257bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
258 int width, int height) {
259 if (!fGpu->supports8BitPalette()) {
260 return false;
261 }
262
bsalomon@google.com0748f212011-02-01 22:56:16 +0000263
reed@google.comac10a2d2010-12-22 21:39:39 +0000264 bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
265
bsalomon@google.com0748f212011-02-01 22:56:16 +0000266 if (!isPow2) {
267 if (!fGpu->npotTextureSupport()) {
268 return false;
269 }
270
271 bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
272 sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
273 if (tiled && !fGpu->npotTextureTileSupport()) {
274 return false;
275 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000276 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000277 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000278}
279
280////////////////////////////////////////////////////////////////////////////////
281
bsalomon@google.com5782d712011-01-21 21:03:59 +0000282void GrContext::setClip(const GrClip& clip) {
283 fGpu->setClip(clip);
284 fGpu->enableState(GrDrawTarget::kClip_StateBit);
285}
286
287void GrContext::setClip(const GrIRect& rect) {
288 GrClip clip;
289 clip.setRect(rect);
290 fGpu->setClip(clip);
291}
292
293////////////////////////////////////////////////////////////////////////////////
294
reed@google.comac10a2d2010-12-22 21:39:39 +0000295void GrContext::eraseColor(GrColor color) {
296 fGpu->eraseColor(color);
297}
298
bsalomon@google.com5782d712011-01-21 21:03:59 +0000299void GrContext::drawPaint(const GrPaint& paint) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000300 // set rect to be big enough to fill the space, but not super-huge, so we
301 // don't overflow fixed-point implementations
302 GrRect r(fGpu->getClip().getBounds());
303 GrMatrix inverse;
304 if (fGpu->getViewInverse(&inverse)) {
305 inverse.mapRect(&r);
306 } else {
307 GrPrintf("---- fGpu->getViewInverse failed\n");
308 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000309 this->drawRect(paint, r);
reed@google.comac10a2d2010-12-22 21:39:39 +0000310}
311
312/* create a triangle strip that strokes the specified triangle. There are 8
313 unique vertices, but we repreat the last 2 to close up. Alternatively we
314 could use an indices array, and then only send 8 verts, but not sure that
315 would be faster.
316 */
317static void setStrokeRectStrip(GrPoint verts[10], const GrRect& rect,
318 GrScalar width) {
319 const GrScalar rad = GrScalarHalf(width);
320
321 verts[0].set(rect.fLeft + rad, rect.fTop + rad);
322 verts[1].set(rect.fLeft - rad, rect.fTop - rad);
323 verts[2].set(rect.fRight - rad, rect.fTop + rad);
324 verts[3].set(rect.fRight + rad, rect.fTop - rad);
325 verts[4].set(rect.fRight - rad, rect.fBottom - rad);
326 verts[5].set(rect.fRight + rad, rect.fBottom + rad);
327 verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
328 verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
329 verts[8] = verts[0];
330 verts[9] = verts[1];
331}
332
bsalomon@google.com5782d712011-01-21 21:03:59 +0000333void GrContext::drawRect(const GrPaint& paint,
334 const GrRect& rect,
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000335 GrScalar width,
336 const GrMatrix* matrix) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000337
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000338 bool textured = NULL != paint.getTexture();
339 GrVertexLayout layout = (textured) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000340 GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
reed@google.comac10a2d2010-12-22 21:39:39 +0000341 0;
342
bsalomon@google.com5782d712011-01-21 21:03:59 +0000343 this->prepareToDraw(paint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000344
reed@google.comac10a2d2010-12-22 21:39:39 +0000345 if (width >= 0) {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000346 // TODO: consider making static vertex buffers for these cases.
347 // Hairline could be done by just adding closing vertex to
348 // unitSquareVertexBuffer()
349 static const int worstCaseVertCount = 10;
350 GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, worstCaseVertCount, 0);
351
352 if (!geo.succeeded()) {
353 return;
354 }
355
356 GrDrawTarget::PrimitiveType primType;
357 int vertCount;
358 GrPoint* vertex = geo.positions();
359
reed@google.comac10a2d2010-12-22 21:39:39 +0000360 if (width > 0) {
361 vertCount = 10;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000362 primType = GrDrawTarget::kTriangleStrip_PrimitiveType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000363 setStrokeRectStrip(vertex, rect, width);
364 } else {
365 // hairline
366 vertCount = 5;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000367 primType = GrDrawTarget::kLineStrip_PrimitiveType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000368 vertex[0].set(rect.fLeft, rect.fTop);
369 vertex[1].set(rect.fRight, rect.fTop);
370 vertex[2].set(rect.fRight, rect.fBottom);
371 vertex[3].set(rect.fLeft, rect.fBottom);
372 vertex[4].set(rect.fLeft, rect.fTop);
373 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000374
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000375 GrDrawTarget::AutoViewMatrixRestore avmr;
376 if (NULL != matrix) {
377 avmr.set(fGpu);
378 fGpu->concatViewMatrix(*matrix);
379 fGpu->concatTextureMatrix(0, *matrix);
380 }
381
382 fGpu->drawNonIndexed(primType, 0, vertCount);
383 } else {
384 #if USE_STATIC_RECT_VB
385 fGpu->setVertexSourceToBuffer(fGpu->unitSquareVertexBuffer(), layout);
386 GrDrawTarget::AutoViewMatrixRestore avmr(fGpu);
387 GrMatrix m;
388 m.setAll(rect.width(), 0, rect.fLeft,
389 0, rect.height(), rect.fTop,
390 0, 0, GrMatrix::I()[8]);
391
392 if (NULL != matrix) {
393 m.postConcat(*matrix);
394 }
395
396 fGpu->concatViewMatrix(m);
397
398 if (textured) {
399 fGpu->concatTextureMatrix(0, m);
400 }
401 #else
402 GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, 4, 0);
403 GrPoint* vertex = geo.positions();
404 vertex->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
405
406 GrDrawTarget::AutoViewMatrixRestore avmr;
407 if (NULL != matrix) {
408 avmr.set(fGpu);
409 fGpu->concatViewMatrix(*matrix);
410 fGpu->concatTextureMatrix(0, *matrix);
411 }
412 #endif
413
414 fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);
415 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000416}
417
bsalomon@google.com5782d712011-01-21 21:03:59 +0000418void GrContext::drawRectToRect(const GrPaint& paint,
419 const GrRect& dstRect,
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000420 const GrRect& srcRect,
421 const GrMatrix* dstMatrix,
422 const GrMatrix* srcMatrix) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000423
424 if (NULL == paint.getTexture()) {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000425 drawRect(paint, dstRect, -1, dstMatrix);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000426 return;
427 }
428
429 this->prepareToDraw(paint);
430
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000431#if USE_STATIC_RECT_VB
432 GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
433 GrDrawTarget::AutoViewMatrixRestore avmr(fGpu);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000434
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000435 GrMatrix m;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000436
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000437 m.setAll(dstRect.width(), 0, dstRect.fLeft,
438 0, dstRect.height(), dstRect.fTop,
439 0, 0, GrMatrix::I()[8]);
440 if (NULL != dstMatrix) {
441 m.postConcat(*dstMatrix);
442 }
443 fGpu->concatViewMatrix(m);
444
445 m.setAll(srcRect.width(), 0, srcRect.fLeft,
446 0, srcRect.height(), srcRect.fTop,
447 0, 0, GrMatrix::I()[8]);
448 if (NULL != srcMatrix) {
449 m.postConcat(*srcMatrix);
450 }
451 fGpu->concatTextureMatrix(0, m);
452
453 fGpu->setVertexSourceToBuffer(fGpu->unitSquareVertexBuffer(), layout);
454#else
455 GrVertexLayout layout = GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
456
457 GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, 4, 0);
458 GrPoint* pos = geo.positions();
459 GrPoint* tex = pos + 1;
460 static const size_t stride = 2 * sizeof(GrPoint);
461 pos[0].setRectFan(dstRect.fLeft, dstRect.fTop,
462 dstRect.fRight, dstRect.fBottom,
463 stride);
464 tex[0].setRectFan(srcRect.fLeft, srcRect.fTop,
465 srcRect.fRight, srcRect.fBottom,
466 stride);
467
468 GrDrawTarget::AutoViewMatrixRestore avmr;
469 if (NULL != dstMatrix) {
470 avmr.set(fGpu);
471 fGpu->concatViewMatrix(*dstMatrix);
472 }
473 if (NULL != srcMatrix) {
474 fGpu->concatTextureMatrix(0, *srcMatrix);
475 }
476
477#endif
478 fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000479}
480
481void GrContext::drawVertices(const GrPaint& paint,
482 GrDrawTarget::PrimitiveType primitiveType,
483 int vertexCount,
484 const GrPoint positions[],
485 const GrPoint texCoords[],
486 const GrColor colors[],
487 const uint16_t indices[],
488 int indexCount) {
489 GrVertexLayout layout = 0;
490 bool interLeave = false;
491
492 GrDrawTarget::AutoReleaseGeometry geo;
493
494 this->prepareToDraw(paint);
495
496 if (NULL != paint.getTexture()) {
497 if (NULL == texCoords) {
498 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
499 } else {
500 layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
501 interLeave = true;
502 }
503 }
504
505 if (NULL != colors) {
506 layout |= GrDrawTarget::kColor_VertexLayoutBit;
507 }
508
509 static const GrVertexLayout interleaveMask =
510 (GrDrawTarget::StageTexCoordVertexLayoutBit(0,0) |
511 GrDrawTarget::kColor_VertexLayoutBit);
512 if (interleaveMask & layout) {
513 if (!geo.set(fGpu, layout, vertexCount, 0)) {
514 GrPrintf("Failed to get space for vertices!");
515 return;
516 }
517 int texOffsets[GrDrawTarget::kMaxTexCoords];
518 int colorOffset;
519 int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
520 texOffsets,
521 &colorOffset);
522 void* curVertex = geo.vertices();
523
524 for (int i = 0; i < vertexCount; ++i) {
525 *((GrPoint*)curVertex) = positions[i];
526
527 if (texOffsets[0] > 0) {
528 *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
529 }
530 if (colorOffset > 0) {
531 *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
532 }
533 curVertex = (void*)((intptr_t)curVertex + vsize);
534 }
535 } else {
536 fGpu->setVertexSourceToArray(positions, layout);
537 }
538
539 if (NULL != indices) {
540 fGpu->setIndexSourceToArray(indices);
541 fGpu->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
542 } else {
543 fGpu->drawNonIndexed(primitiveType, 0, vertexCount);
544 }
545}
546
547
reed@google.comac10a2d2010-12-22 21:39:39 +0000548////////////////////////////////////////////////////////////////////////////////
549
550#define NEW_EVAL 1 // Use adaptive path tesselation
551#define STENCIL_OFF 0 // Always disable stencil (even when needed)
552#define CPU_TRANSFORM 0 // Transform path verts on CPU
553
554#if NEW_EVAL
555
556#define EVAL_TOL GR_Scalar1
557
558static uint32_t quadratic_point_count(const GrPoint points[], GrScalar tol) {
559 GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]);
560 // TODO: fixed points sqrt
561 if (d < tol) {
562 return 1;
563 } else {
564 // Each time we subdivide, d should be cut in 4. So we need to
565 // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)
566 // points.
567 // 2^(log4(x)) = sqrt(x);
568 d = ceilf(sqrtf(d/tol));
569 return GrNextPow2((uint32_t)d);
570 }
571}
572
573static uint32_t generate_quadratic_points(const GrPoint& p0,
574 const GrPoint& p1,
575 const GrPoint& p2,
576 GrScalar tolSqd,
577 GrPoint** points,
578 uint32_t pointsLeft) {
579 if (pointsLeft < 2 ||
580 (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) {
581 (*points)[0] = p2;
582 *points += 1;
583 return 1;
584 }
585
586 GrPoint q[] = {
587 GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
588 GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
589 };
590 GrPoint r(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY));
591
592 pointsLeft >>= 1;
593 uint32_t a = generate_quadratic_points(p0, q[0], r, tolSqd, points, pointsLeft);
594 uint32_t b = generate_quadratic_points(r, q[1], p2, tolSqd, points, pointsLeft);
595 return a + b;
596}
597
598static uint32_t cubic_point_count(const GrPoint points[], GrScalar tol) {
599 GrScalar d = GrMax(points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),
600 points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));
601 d = sqrtf(d);
602 if (d < tol) {
603 return 1;
604 } else {
605 d = ceilf(sqrtf(d/tol));
606 return GrNextPow2((uint32_t)d);
607 }
608}
609
610static uint32_t generate_cubic_points(const GrPoint& p0,
611 const GrPoint& p1,
612 const GrPoint& p2,
613 const GrPoint& p3,
614 GrScalar tolSqd,
615 GrPoint** points,
616 uint32_t pointsLeft) {
617 if (pointsLeft < 2 ||
618 (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd &&
619 p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) {
620 (*points)[0] = p3;
621 *points += 1;
622 return 1;
623 }
624 GrPoint q[] = {
625 GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
626 GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
627 GrPoint(GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY))
628 };
629 GrPoint r[] = {
630 GrPoint(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)),
631 GrPoint(GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY))
632 };
633 GrPoint s(GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY));
634 pointsLeft >>= 1;
635 uint32_t a = generate_cubic_points(p0, q[0], r[0], s, tolSqd, points, pointsLeft);
636 uint32_t b = generate_cubic_points(s, r[1], q[2], p3, tolSqd, points, pointsLeft);
637 return a + b;
638}
639
640#else // !NEW_EVAL
641
642static GrScalar gr_eval_quad(const GrScalar coord[], GrScalar t) {
643 GrScalar A = coord[0] - 2 * coord[2] + coord[4];
644 GrScalar B = 2 * (coord[2] - coord[0]);
645 GrScalar C = coord[0];
646
647 return GrMul(GrMul(A, t) + B, t) + C;
648}
649
650static void gr_eval_quad_at(const GrPoint src[3], GrScalar t, GrPoint* pt) {
651 GrAssert(src);
652 GrAssert(pt);
653 GrAssert(t >= 0 && t <= GR_Scalar1);
654 pt->set(gr_eval_quad(&src[0].fX, t), gr_eval_quad(&src[0].fY, t));
655}
656
657static GrScalar gr_eval_cubic(const GrScalar coord[], GrScalar t) {
658 GrScalar A = coord[6] - coord[0] + 3 * (coord[2] - coord[4]);
659 GrScalar B = 3 * (coord[0] - 2 * coord[2] + coord[4]);
660 GrScalar C = 3 * (coord[2] - coord[0]);
661 GrScalar D = coord[0];
662
663 return GrMul(GrMul(GrMul(A, t) + B, t) + C, t) + D;
664}
665
666static void gr_eval_cubic_at(const GrPoint src[4], GrScalar t, GrPoint* pt) {
667 GrAssert(src);
668 GrAssert(pt);
669 GrAssert(t >= 0 && t <= GR_Scalar1);
670
671 pt->set(gr_eval_cubic(&src[0].fX, t), gr_eval_cubic(&src[0].fY, t));
672}
673
674#endif // !NEW_EVAL
675
676static int worst_case_point_count(GrPathIter* path,
677 int* subpaths,
678 const GrMatrix& matrix,
679 GrScalar tol) {
680 int pointCount = 0;
681 *subpaths = 1;
682
683 bool first = true;
684
685 GrPathIter::Command cmd;
686
687 GrPoint pts[4];
688 while ((cmd = path->next(pts)) != GrPathIter::kEnd_Command) {
689
690 switch (cmd) {
691 case GrPathIter::kLine_Command:
692 pointCount += 1;
693 break;
694 case GrPathIter::kQuadratic_Command:
695#if NEW_EVAL
696 matrix.mapPoints(pts, pts, 3);
697 pointCount += quadratic_point_count(pts, tol);
698#else
699 pointCount += 9;
700#endif
701 break;
702 case GrPathIter::kCubic_Command:
703#if NEW_EVAL
704 matrix.mapPoints(pts, pts, 4);
705 pointCount += cubic_point_count(pts, tol);
706#else
707 pointCount += 17;
708#endif
709 break;
710 case GrPathIter::kMove_Command:
711 pointCount += 1;
712 if (!first) {
713 ++(*subpaths);
714 }
715 break;
716 default:
717 break;
718 }
719 first = false;
720 }
721 return pointCount;
722}
723
724static inline bool single_pass_path(const GrPathIter& path,
725 GrContext::PathFills fill,
reed@google.comac10a2d2010-12-22 21:39:39 +0000726 const GrGpu& gpu) {
727#if STENCIL_OFF
728 return true;
729#else
730 if (GrContext::kEvenOdd_PathFill == fill) {
731 GrPathIter::ConvexHint hint = path.hint();
732 return hint == GrPathIter::kConvex_ConvexHint ||
733 hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint;
734 } else if (GrContext::kWinding_PathFill == fill) {
735 GrPathIter::ConvexHint hint = path.hint();
736 return hint == GrPathIter::kConvex_ConvexHint ||
737 hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint ||
738 (hint == GrPathIter::kSameWindingConvexPieces_ConvexHint &&
739 gpu.canDisableBlend() && !gpu.isDitherState());
740
741 }
742 return false;
743#endif
744}
745
bsalomon@google.com5782d712011-01-21 21:03:59 +0000746void GrContext::drawPath(const GrPaint& paint,
747 GrPathIter* path,
748 PathFills fill,
749 const GrPoint* translate) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000750
reed@google.comac10a2d2010-12-22 21:39:39 +0000751
bsalomon@google.com5782d712011-01-21 21:03:59 +0000752 this->prepareToDraw(paint);
753
754 GrDrawTarget::AutoStateRestore asr(fGpu);
reed@google.comac10a2d2010-12-22 21:39:39 +0000755
756#if NEW_EVAL
bsalomon@google.com5782d712011-01-21 21:03:59 +0000757 GrMatrix viewM = fGpu->getViewMatrix();
reed@google.comac10a2d2010-12-22 21:39:39 +0000758 // In order to tesselate the path we get a bound on how much the matrix can
759 // stretch when mapping to screen coordinates.
760 GrScalar stretch = viewM.getMaxStretch();
761 bool useStretch = stretch > 0;
762 GrScalar tol = EVAL_TOL;
763 if (!useStretch) {
764 // TODO: deal with perspective in some better way.
765 tol /= 10;
766 } else {
767 // TODO: fixed point divide
768 GrScalar sinv = 1 / stretch;
769 tol = GrMul(tol, sinv);
770 viewM = GrMatrix::I();
771 }
772 GrScalar tolSqd = GrMul(tol, tol);
773#else
774 // pass to worst_case... but won't be used.
775 static const GrScalar tol = -1;
776#endif
777
778 int subpathCnt;
779 int maxPts = worst_case_point_count(path,
780 &subpathCnt,
781#if CPU_TRANSFORM
782 cpuMatrix,
783#else
784 GrMatrix::I(),
785#endif
786 tol);
787 GrVertexLayout layout = 0;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000788
789 if (NULL != paint.getTexture()) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000790 layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000791 }
792 // add 4 to hold the bounding rect
793 GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, maxPts + 4, 0);
794
795 GrPoint* base = (GrPoint*) arg.vertices();
796 GrPoint* vert = base;
797 GrPoint* subpathBase = base;
798
799 GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
800
801 path->rewind();
802
803 // TODO: use primitve restart if available rather than multiple draws
bsalomon@google.com5782d712011-01-21 21:03:59 +0000804 GrDrawTarget::PrimitiveType type;
reed@google.comac10a2d2010-12-22 21:39:39 +0000805 int passCount = 0;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000806 GrDrawTarget::StencilPass passes[3];
reed@google.comac10a2d2010-12-22 21:39:39 +0000807 bool reverse = false;
808
809 if (kHairLine_PathFill == fill) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000810 type = GrDrawTarget::kLineStrip_PrimitiveType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000811 passCount = 1;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000812 passes[0] = GrDrawTarget::kNone_StencilPass;
reed@google.comac10a2d2010-12-22 21:39:39 +0000813 } else {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000814 type = GrDrawTarget::kTriangleFan_PrimitiveType;
815 if (single_pass_path(*path, fill, *fGpu)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000816 passCount = 1;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000817 passes[0] = GrDrawTarget::kNone_StencilPass;
reed@google.comac10a2d2010-12-22 21:39:39 +0000818 } else {
819 switch (fill) {
820 case kInverseEvenOdd_PathFill:
821 reverse = true;
822 // fallthrough
823 case kEvenOdd_PathFill:
824 passCount = 2;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000825 passes[0] = GrDrawTarget::kEvenOddStencil_StencilPass;
826 passes[1] = GrDrawTarget::kEvenOddColor_StencilPass;
reed@google.comac10a2d2010-12-22 21:39:39 +0000827 break;
828
829 case kInverseWinding_PathFill:
830 reverse = true;
831 // fallthrough
832 case kWinding_PathFill:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000833 passes[0] = GrDrawTarget::kWindingStencil1_StencilPass;
reed@google.comac10a2d2010-12-22 21:39:39 +0000834 if (fGpu->supportsSingleStencilPassWinding()) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000835 passes[1] = GrDrawTarget::kWindingColor_StencilPass;
reed@google.comac10a2d2010-12-22 21:39:39 +0000836 passCount = 2;
837 } else {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000838 passes[1] = GrDrawTarget::kWindingStencil2_StencilPass;
839 passes[2] = GrDrawTarget::kWindingColor_StencilPass;
reed@google.comac10a2d2010-12-22 21:39:39 +0000840 passCount = 3;
841 }
842 break;
843 default:
844 GrAssert(!"Unknown path fill!");
845 return;
846 }
847 }
848 }
849 fGpu->setReverseFill(reverse);
850#if CPU_TRANSFORM
851 GrMatrix cpuMatrix;
852 fGpu->getViewMatrix(&cpuMatrix);
853 fGpu->setViewMatrix(GrMatrix::I());
854#endif
855
856 GrPoint pts[4];
857
858 bool first = true;
859 int subpath = 0;
860
861 for (;;) {
862 GrPathIter::Command cmd = path->next(pts);
863#if CPU_TRANSFORM
864 int numPts = GrPathIter::NumCommandPoints(cmd);
865 cpuMatrix.mapPoints(pts, pts, numPts);
866#endif
867 switch (cmd) {
868 case GrPathIter::kMove_Command:
869 if (!first) {
870 subpathVertCount[subpath] = vert-subpathBase;
871 subpathBase = vert;
872 ++subpath;
873 }
874 *vert = pts[0];
875 vert++;
876 break;
877 case GrPathIter::kLine_Command:
878 *vert = pts[1];
879 vert++;
880 break;
881 case GrPathIter::kQuadratic_Command: {
882#if NEW_EVAL
883
884 generate_quadratic_points(pts[0], pts[1], pts[2],
885 tolSqd, &vert,
886 quadratic_point_count(pts, tol));
887#else
888 const int n = 8;
889 const GrScalar dt = GR_Scalar1 / n;
890 GrScalar t = dt;
891 for (int i = 1; i < n; i++) {
892 gr_eval_quad_at(pts, t, (GrPoint*)vert);
893 t += dt;
894 vert++;
895 }
896 vert->set(pts[2].fX, pts[2].fY);
897 vert++;
898#endif
899 break;
900 }
901 case GrPathIter::kCubic_Command: {
902#if NEW_EVAL
903 generate_cubic_points(pts[0], pts[1], pts[2], pts[3],
904 tolSqd, &vert,
905 cubic_point_count(pts, tol));
906#else
907 const int n = 16;
908 const GrScalar dt = GR_Scalar1 / n;
909 GrScalar t = dt;
910 for (int i = 1; i < n; i++) {
911 gr_eval_cubic_at(pts, t, (GrPoint*)vert);
912 t += dt;
913 vert++;
914 }
915 vert->set(pts[3].fX, pts[3].fY);
916 vert++;
917#endif
918 break;
919 }
920 case GrPathIter::kClose_Command:
921 break;
922 case GrPathIter::kEnd_Command:
923 subpathVertCount[subpath] = vert-subpathBase;
924 ++subpath; // this could be only in debug
925 goto FINISHED;
926 }
927 first = false;
928 }
929FINISHED:
930 GrAssert(subpath == subpathCnt);
931 GrAssert((vert - base) <= maxPts);
932
933 if (translate) {
934 int count = vert - base;
935 for (int i = 0; i < count; i++) {
936 base[i].offset(translate->fX, translate->fY);
937 }
938 }
939
940 // arbitrary path complexity cutoff
941 bool useBounds = fill != kHairLine_PathFill &&
942 (reverse || (vert - base) > 8);
943 GrPoint* boundsVerts = base + maxPts;
944 if (useBounds) {
945 GrRect bounds;
946 if (reverse) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000947 GrAssert(NULL != fGpu->getRenderTarget());
reed@google.comac10a2d2010-12-22 21:39:39 +0000948 // draw over the whole world.
949 bounds.setLTRB(0, 0,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000950 GrIntToScalar(fGpu->getRenderTarget()->width()),
951 GrIntToScalar(fGpu->getRenderTarget()->height()));
952 GrMatrix vmi;
953 if (fGpu->getViewInverse(&vmi)) {
954 vmi.mapRect(&bounds);
955 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000956 } else {
957 bounds.setBounds((GrPoint*)base, vert - base);
958 }
959 boundsVerts[0].setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight,
960 bounds.fBottom);
961 }
962
963 for (int p = 0; p < passCount; ++p) {
964 fGpu->setStencilPass(passes[p]);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000965 if (useBounds && (GrDrawTarget::kEvenOddColor_StencilPass == passes[p] ||
966 GrDrawTarget::kWindingColor_StencilPass == passes[p])) {
967 fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +0000968 maxPts, 4);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000969
reed@google.comac10a2d2010-12-22 21:39:39 +0000970 } else {
971 int baseVertex = 0;
972 for (int sp = 0; sp < subpathCnt; ++sp) {
973 fGpu->drawNonIndexed(type,
974 baseVertex,
975 subpathVertCount[sp]);
976 baseVertex += subpathVertCount[sp];
977 }
978 }
979 }
980}
981
bsalomon@google.com5782d712011-01-21 21:03:59 +0000982////////////////////////////////////////////////////////////////////////////////
983
reed@google.comac10a2d2010-12-22 21:39:39 +0000984void GrContext::flush(bool flushRenderTarget) {
985 flushText();
986 if (flushRenderTarget) {
987 fGpu->forceRenderTargetFlush();
988 }
989}
990
991void GrContext::flushText() {
992 fTextDrawBuffer.playback(fGpu);
993 fTextDrawBuffer.reset();
994}
995
996bool GrContext::readPixels(int left, int top, int width, int height,
997 GrTexture::PixelConfig config, void* buffer) {
998 this->flush(true);
999 return fGpu->readPixels(left, top, width, height, config, buffer);
1000}
1001
1002void GrContext::writePixels(int left, int top, int width, int height,
1003 GrTexture::PixelConfig config, const void* buffer,
1004 size_t stride) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001005
1006 // TODO: when underlying api has a direct way to do this we should use it
1007 // (e.g. glDrawPixels on desktop GL).
1008
reed@google.comac10a2d2010-12-22 21:39:39 +00001009 const GrGpu::TextureDesc desc = {
1010 0, GrGpu::kNone_AALevel, width, height, config
1011 };
1012 GrTexture* texture = fGpu->createTexture(desc, buffer, stride);
1013 if (NULL == texture) {
1014 return;
1015 }
1016
1017 this->flush(true);
1018
1019 GrAutoUnref aur(texture);
1020 GrDrawTarget::AutoStateRestore asr(fGpu);
1021
1022 GrMatrix matrix;
1023 matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
1024 fGpu->setViewMatrix(matrix);
1025 matrix.setScale(GR_Scalar1 / texture->allocWidth(),
1026 GR_Scalar1 / texture->allocHeight());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001027 fGpu->setTextureMatrix(0, matrix);
reed@google.comac10a2d2010-12-22 21:39:39 +00001028
1029 fGpu->disableState(GrDrawTarget::kClip_StateBit);
1030 fGpu->setAlpha(0xFF);
1031 fGpu->setBlendFunc(GrDrawTarget::kOne_BlendCoeff,
1032 GrDrawTarget::kZero_BlendCoeff);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001033 fGpu->setTexture(0, texture);
1034 fGpu->setSamplerState(0, GrSamplerState::ClampNoFilter());
reed@google.comac10a2d2010-12-22 21:39:39 +00001035
bsalomon@google.com5782d712011-01-21 21:03:59 +00001036 GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
1037 static const int VCOUNT = 4;
1038
1039 GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
1040 if (!geo.succeeded()) {
1041 return;
1042 }
1043 ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
1044 fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, VCOUNT);
1045}
1046////////////////////////////////////////////////////////////////////////////////
1047
1048void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
1049 target->setTexture(0, paint.getTexture());
1050 target->setTextureMatrix(0, paint.fTextureMatrix);
1051 target->setSamplerState(0, paint.fSampler);
1052 target->setColor(paint.fColor);
1053
1054 if (paint.fDither) {
1055 target->enableState(GrDrawTarget::kDither_StateBit);
1056 } else {
1057 target->disableState(GrDrawTarget::kDither_StateBit);
1058 }
1059 if (paint.fAntiAlias) {
1060 target->enableState(GrDrawTarget::kAntialias_StateBit);
1061 } else {
1062 target->disableState(GrDrawTarget::kAntialias_StateBit);
1063 }
1064 target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
1065}
1066
1067void GrContext::prepareToDraw(const GrPaint& paint) {
1068
1069 flushText();
1070 SetPaint(paint, fGpu);
reed@google.comac10a2d2010-12-22 21:39:39 +00001071}
1072
1073////////////////////////////////////////////////////////////////////////////////
1074
reed@google.comac10a2d2010-12-22 21:39:39 +00001075void GrContext::resetContext() {
1076 fGpu->resetContext();
1077}
1078
reed@google.comac10a2d2010-12-22 21:39:39 +00001079void GrContext::setRenderTarget(GrRenderTarget* target) {
1080 flushText();
1081 fGpu->setRenderTarget(target);
1082}
1083
bsalomon@google.com5782d712011-01-21 21:03:59 +00001084GrRenderTarget* GrContext::getRenderTarget() {
1085 return fGpu->getRenderTarget();
reed@google.comac10a2d2010-12-22 21:39:39 +00001086}
1087
bsalomon@google.com5782d712011-01-21 21:03:59 +00001088const GrRenderTarget* GrContext::getRenderTarget() const {
1089 return fGpu->getRenderTarget();
reed@google.comac10a2d2010-12-22 21:39:39 +00001090}
1091
bsalomon@google.com5782d712011-01-21 21:03:59 +00001092const GrMatrix& GrContext::getMatrix() const {
1093 return fGpu->getViewMatrix();
reed@google.comac10a2d2010-12-22 21:39:39 +00001094}
1095
bsalomon@google.com5782d712011-01-21 21:03:59 +00001096void GrContext::setMatrix(const GrMatrix& m) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001097 fGpu->setViewMatrix(m);
1098}
1099
bsalomon@google.com5782d712011-01-21 21:03:59 +00001100void GrContext::concatMatrix(const GrMatrix& m) const {
1101 fGpu->concatViewMatrix(m);
reed@google.comac10a2d2010-12-22 21:39:39 +00001102}
1103
1104static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
1105 intptr_t mask = 1 << shift;
1106 if (pred) {
1107 bits |= mask;
1108 } else {
1109 bits &= ~mask;
1110 }
1111 return bits;
1112}
1113
reed@google.comac10a2d2010-12-22 21:39:39 +00001114void GrContext::resetStats() {
1115 fGpu->resetStats();
1116}
1117
1118const GrGpu::Stats& GrContext::getStats() const {
1119 return fGpu->getStats();
1120}
1121
1122void GrContext::printStats() const {
1123 fGpu->printStats();
1124}
1125
1126GrContext::GrContext(GrGpu* gpu) :
1127 fVBAllocPool(gpu,
1128 gpu->supportsBufferLocking() ? POOL_VB_SIZE : 0,
1129 gpu->supportsBufferLocking() ? NUM_POOL_VBS : 0),
1130 fTextDrawBuffer(gpu->supportsBufferLocking() ? &fVBAllocPool : NULL) {
1131 fGpu = gpu;
1132 fGpu->ref();
1133 fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT,
1134 MAX_TEXTURE_CACHE_BYTES);
1135 fFontCache = new GrFontCache(fGpu);
1136}
1137
1138bool GrContext::finalizeTextureKey(GrTextureKey* key,
1139 const GrSamplerState& sampler) const {
1140 uint32_t bits = 0;
1141 uint16_t width = key->width();
1142 uint16_t height = key->height();
bsalomon@google.com0748f212011-02-01 22:56:16 +00001143
1144
1145 if (!fGpu->npotTextureTileSupport()) {
1146 bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
1147
1148 bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
1149 (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
1150
1151 if (tiled && !isPow2) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001152 bits |= 1;
1153 bits |= sampler.isFilter() ? 2 : 0;
1154 }
1155 }
1156 key->finalize(bits);
1157 return 0 != bits;
1158}
1159
bsalomon@google.com5782d712011-01-21 21:03:59 +00001160GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
1161 GrDrawTarget* target;
reed@google.comac10a2d2010-12-22 21:39:39 +00001162#if DEFER_TEXT_RENDERING
1163 fTextDrawBuffer.initializeDrawStateAndClip(*fGpu);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001164 target = &fTextDrawBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +00001165#else
bsalomon@google.com5782d712011-01-21 21:03:59 +00001166 target = fGpu;
reed@google.comac10a2d2010-12-22 21:39:39 +00001167#endif
bsalomon@google.com5782d712011-01-21 21:03:59 +00001168 SetPaint(paint, target);
1169 return target;
reed@google.comac10a2d2010-12-22 21:39:39 +00001170}
1171
1172const GrIndexBuffer* GrContext::quadIndexBuffer() const {
1173 return fGpu->quadIndexBuffer();
1174}
1175
1176int GrContext::maxQuadsInIndexBuffer() const {
1177 return fGpu->maxQuadsInIndexBuffer();
1178}
1179
1180
1181