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