blob: cc7cb7bb59b03c41535bb82361259c0228dc573e [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "GrContext.h"
19#include "GrTextContext.h"
20
reed@google.comac10a2d2010-12-22 21:39:39 +000021#include "SkGpuDevice.h"
reed@google.com7b201d22011-01-11 18:59:23 +000022#include "SkGpuDeviceFactory.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000023#include "SkGrTexturePixelRef.h"
24
25#include "SkDrawProcs.h"
26#include "SkGlyphCache.h"
27
28#define CACHE_LAYER_TEXTURES 1
29
30#if 0
31 extern bool (*gShouldDrawProc)();
32 #define CHECK_SHOULD_DRAW(draw) \
33 do { \
34 if (gShouldDrawProc && !gShouldDrawProc()) return; \
35 this->prepareRenderTarget(draw); \
36 } while (0)
37#else
38 #define CHECK_SHOULD_DRAW(draw) this->prepareRenderTarget(draw)
39#endif
40
41class SkAutoExtMatrix {
42public:
43 SkAutoExtMatrix(const SkMatrix* extMatrix) {
44 if (extMatrix) {
45 SkGr::SkMatrix2GrMatrix(*extMatrix, &fMatrix);
46 fExtMatrix = &fMatrix;
47 } else {
48 fExtMatrix = NULL;
49 }
50 }
51 const GrMatrix* extMatrix() const { return fExtMatrix; }
52
53private:
54 GrMatrix fMatrix;
55 GrMatrix* fExtMatrix; // NULL or &fMatrix
56};
57
58///////////////////////////////////////////////////////////////////////////////
59
60SkGpuDevice::SkAutoCachedTexture::
61 SkAutoCachedTexture(SkGpuDevice* device,
62 const SkBitmap& bitmap,
63 const GrSamplerState& sampler,
64 GrTexture** texture) {
65 GrAssert(texture);
66 fTex = NULL;
67 *texture = this->set(device, bitmap, sampler);
68}
69
70SkGpuDevice::SkAutoCachedTexture::SkAutoCachedTexture() {
71 fTex = NULL;
72}
73
74GrTexture* SkGpuDevice::SkAutoCachedTexture::set(SkGpuDevice* device,
75 const SkBitmap& bitmap,
76 const GrSamplerState& sampler) {
77 if (fTex) {
78 fDevice->unlockCachedTexture(fTex);
79 }
80 fDevice = device;
81 GrTexture* texture = (GrTexture*)bitmap.getTexture();
82 if (texture) {
83 // return the native texture
84 fTex = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +000085 } else {
86 // look it up in our cache
87 fTex = device->lockCachedTexture(bitmap, sampler, &texture, false);
88 }
89 return texture;
90}
91
92SkGpuDevice::SkAutoCachedTexture::~SkAutoCachedTexture() {
93 if (fTex) {
94 fDevice->unlockCachedTexture(fTex);
95 }
96}
97
98///////////////////////////////////////////////////////////////////////////////
99
100bool gDoTraceDraw;
101
102struct GrSkDrawProcs : public SkDrawProcs {
103public:
104 GrContext* fContext;
105 GrTextContext* fTextContext;
106 GrFontScaler* fFontScaler; // cached in the skia glyphcache
107};
108
109///////////////////////////////////////////////////////////////////////////////
110
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000111GrRenderTarget* SkGpuDevice::Current3DApiRenderTarget() {
112 return (GrRenderTarget*) -1;
113}
114
115SkGpuDevice::SkGpuDevice(GrContext* context,
116 const SkBitmap& bitmap,
117 GrRenderTarget* renderTargetOrNull)
118 : SkDevice(NULL, bitmap, (NULL == renderTargetOrNull)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000119
120 fNeedPrepareRenderTarget = false;
121 fDrawProcs = NULL;
122
reed@google.com7b201d22011-01-11 18:59:23 +0000123 fContext = context;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000124 fContext->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000125
126 fCache = NULL;
127 fTexture = NULL;
128 fRenderTarget = NULL;
129 fNeedClear = false;
130
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000131 if (NULL == renderTargetOrNull) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000132 SkBitmap::Config c = bitmap.config();
133 if (c != SkBitmap::kRGB_565_Config) {
134 c = SkBitmap::kARGB_8888_Config;
135 }
136 SkBitmap bm;
137 bm.setConfig(c, this->width(), this->height());
138
139#if CACHE_LAYER_TEXTURES
140
141 fCache = this->lockCachedTexture(bm, GrSamplerState::ClampNoFilter(),
142 &fTexture, true);
143 if (fCache) {
144 SkASSERT(NULL != fTexture);
145 SkASSERT(fTexture->isRenderTarget());
146 }
147#else
148 const GrGpu::TextureDesc desc = {
149 GrGpu::kRenderTarget_TextureFlag,
150 GrGpu::kNone_AALevel,
151 this->width(),
152 this->height(),
153 SkGr::Bitmap2PixelConfig(bm)
154 };
155
156 fTexture = fContext->createUncachedTexture(desc, NULL, 0);
157#endif
158 if (NULL != fTexture) {
159 fRenderTarget = fTexture->asRenderTarget();
160
161 GrAssert(NULL != fRenderTarget);
162
163 // we defer the actual clear until our gainFocus()
164 fNeedClear = true;
165
166 // wrap the bitmap with a pixelref to expose our texture
167 SkGrTexturePixelRef* pr = new SkGrTexturePixelRef(fTexture);
168 this->setPixelRef(pr, 0)->unref();
169 } else {
170 GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
171 this->width(), this->height());
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000172 GrAssert(false);
reed@google.comac10a2d2010-12-22 21:39:39 +0000173 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000174 } else if (Current3DApiRenderTarget() == renderTargetOrNull) {
175 fRenderTarget = fContext->createRenderTargetFrom3DApiState();
176 } else {
177 fRenderTarget = renderTargetOrNull;
reed@google.comac10a2d2010-12-22 21:39:39 +0000178 fRenderTarget->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000179 }
180}
181
182SkGpuDevice::~SkGpuDevice() {
183 if (fDrawProcs) {
184 delete fDrawProcs;
185 }
186
187 if (fCache) {
188 GrAssert(NULL != fTexture);
189 GrAssert(fRenderTarget == fTexture->asRenderTarget());
190 // IMPORTANT: reattach the rendertarget/tex back to the cache.
191 fContext->reattachAndUnlockCachedTexture((GrTextureEntry*)fCache);
192 } else if (NULL != fTexture) {
193 GrAssert(!CACHE_LAYER_TEXTURES);
194 GrAssert(fRenderTarget == fTexture->asRenderTarget());
195 fTexture->unref();
196 } else if (NULL != fRenderTarget) {
197 fRenderTarget->unref();
198 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000199 fContext->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000200}
201
reed@google.comac10a2d2010-12-22 21:39:39 +0000202intptr_t SkGpuDevice::getLayerTextureHandle() const {
203 if (fTexture) {
204 return fTexture->getTextureHandle();
205 } else {
206 return 0;
207 }
208}
209///////////////////////////////////////////////////////////////////////////////
210
211void SkGpuDevice::makeRenderTargetCurrent() {
212 fContext->setRenderTarget(fRenderTarget);
213 fContext->flush(true);
214 fNeedPrepareRenderTarget = true;
215}
216
217///////////////////////////////////////////////////////////////////////////////
218
219bool SkGpuDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
220 SkIRect bounds;
221 bounds.set(0, 0, this->width(), this->height());
222 if (!bounds.intersect(srcRect)) {
223 return false;
224 }
225
226 const int w = bounds.width();
227 const int h = bounds.height();
228 SkBitmap tmp;
229 // note we explicitly specify our rowBytes to be snug (no gap between rows)
230 tmp.setConfig(SkBitmap::kARGB_8888_Config, w, h, w * 4);
231 if (!tmp.allocPixels()) {
232 return false;
233 }
234
235 SkAutoLockPixels alp(tmp);
236 fContext->setRenderTarget(fRenderTarget);
237 // we aren't setting the clip or matrix, so mark as dirty
238 // we don't need to set them for this call and don't have them anyway
239 fNeedPrepareRenderTarget = true;
240
241 if (!fContext->readPixels(bounds.fLeft, bounds.fTop,
242 bounds.width(), bounds.height(),
243 GrTexture::kRGBA_8888_PixelConfig,
244 tmp.getPixels())) {
245 return false;
246 }
247
248 tmp.swap(*bitmap);
249 return true;
250}
251
252void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y) {
253 SkAutoLockPixels alp(bitmap);
254 if (!bitmap.readyToDraw()) {
255 return;
256 }
257 GrTexture::PixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(),
258 bitmap.isOpaque());
259 fContext->setRenderTarget(fRenderTarget);
260 // we aren't setting the clip or matrix, so mark as dirty
261 // we don't need to set them for this call and don't have them anyway
262 fNeedPrepareRenderTarget = true;
263
264 fContext->writePixels(x, y, bitmap.width(), bitmap.height(),
265 config, bitmap.getPixels(), bitmap.rowBytes());
266}
267
268///////////////////////////////////////////////////////////////////////////////
269
270static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
271 const SkRegion& clip) {
272 GrMatrix grmat;
273 SkGr::SkMatrix2GrMatrix(matrix, &grmat);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000274 context->setMatrix(grmat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000275
276 SkGrClipIterator iter;
277 iter.reset(clip);
278 GrClip grc(&iter);
279 if (context->getClip() == grc) {
280 } else {
281 context->setClip(grc);
282 }
283}
284
285// call this ever each draw call, to ensure that the context reflects our state,
286// and not the state from some other canvas/device
287void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) {
288 if (fNeedPrepareRenderTarget ||
bsalomon@google.com5782d712011-01-21 21:03:59 +0000289 fContext->getRenderTarget() != fRenderTarget) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000290
291 fContext->setRenderTarget(fRenderTarget);
292 convert_matrixclip(fContext, *draw.fMatrix, *draw.fClip);
293 fNeedPrepareRenderTarget = false;
294 }
295}
296
297void SkGpuDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& clip) {
298 this->INHERITED::setMatrixClip(matrix, clip);
299
300 convert_matrixclip(fContext, matrix, clip);
301}
302
303void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix,
304 const SkRegion& clip) {
305 fContext->setRenderTarget(fRenderTarget);
306
307 this->INHERITED::gainFocus(canvas, matrix, clip);
308
309 convert_matrixclip(fContext, matrix, clip);
310
311 if (fNeedClear) {
312 fContext->eraseColor(0x0);
313 fNeedClear = false;
314 }
315}
316
bsalomon@google.com5782d712011-01-21 21:03:59 +0000317bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint, SkPoint* max) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000318 if (NULL != fTexture) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000319 paint->setTexture(fTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +0000320 if (NULL != max) {
321 max->set(SkFixedToScalar((width() << 16) /
322 fTexture->allocWidth()),
323 SkFixedToScalar((height() << 16) /
324 fTexture->allocHeight()));
325 }
326 return true;
327 }
328 return false;
329}
330
331///////////////////////////////////////////////////////////////////////////////
332
bsalomon@google.com5782d712011-01-21 21:03:59 +0000333// must be in SkShader::BitmapTypeOrder
reed@google.comac10a2d2010-12-22 21:39:39 +0000334
bsalomon@google.com5782d712011-01-21 21:03:59 +0000335static const GrSamplerState::SampleMode sk_bmp_type_to_sample_mode[] = {
336 (GrSamplerState::SampleMode) -1, // kNone_BitmapType
337 GrSamplerState::kNormal_SampleMode, // kDefault_BitmapType
338 GrSamplerState::kRadial_SampleMode, // kRadial_BitmapType
339 GrSamplerState::kSweep_SampleMode, // kSweep_BitmapType
340 GrSamplerState::kRadial2_SampleMode, // kTwoPointRadial_BitmapType
341};
342
343bool SkGpuDevice::skPaint2GrPaintNoShader(const SkPaint& skPaint,
344 bool justAlpha,
345 GrPaint* grPaint) {
346
347 grPaint->fDither = skPaint.isDither();
348 grPaint->fAntiAlias = skPaint.isAntiAlias();
349
350 SkXfermode::Coeff sm = SkXfermode::kOne_Coeff;
351 SkXfermode::Coeff dm = SkXfermode::kISA_Coeff;
352
353 SkXfermode* mode = skPaint.getXfermode();
354 if (mode) {
355 if (!mode->asCoeff(&sm, &dm)) {
reed@google.com1a2e8d22011-01-21 22:08:29 +0000356 SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
bsalomon@google.com5782d712011-01-21 21:03:59 +0000357#if 0
358 return false;
359#endif
360 }
361 }
362 grPaint->fSrcBlendCoeff = sk_blend_to_grblend(sm);
363 grPaint->fDstBlendCoeff = sk_blend_to_grblend(dm);
364
365 if (justAlpha) {
366 uint8_t alpha = skPaint.getAlpha();
367 grPaint->fColor = GrColorPackRGBA(alpha, alpha, alpha, alpha);
368 } else {
369 grPaint->fColor = SkGr::SkColor2GrColor(skPaint.getColor());
370 grPaint->setTexture(NULL);
371 }
372 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000373}
374
bsalomon@google.com5782d712011-01-21 21:03:59 +0000375bool SkGpuDevice::skPaint2GrPaintShader(const SkPaint& skPaint,
376 SkAutoCachedTexture* act,
377 const SkMatrix& ctm,
378 GrPaint* grPaint) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000379
bsalomon@google.com5782d712011-01-21 21:03:59 +0000380 SkASSERT(NULL != act);
reed@google.comac10a2d2010-12-22 21:39:39 +0000381
bsalomon@google.com5782d712011-01-21 21:03:59 +0000382 SkShader* shader = skPaint.getShader();
reed@google.comac10a2d2010-12-22 21:39:39 +0000383 if (NULL == shader) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000384 return this->skPaint2GrPaintNoShader(skPaint, false, grPaint);
385 grPaint->setTexture(NULL);
386 return true;
387 } else if (!this->skPaint2GrPaintNoShader(skPaint, true, grPaint)) {
388 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000389 }
390
bsalomon@google.com5782d712011-01-21 21:03:59 +0000391 SkPaint noAlphaPaint(skPaint);
392 noAlphaPaint.setAlpha(255);
393 shader->setContext(this->accessBitmap(false), noAlphaPaint, ctm);
reed@google.comac10a2d2010-12-22 21:39:39 +0000394
reed@google.comac10a2d2010-12-22 21:39:39 +0000395 SkBitmap bitmap;
396 SkMatrix matrix;
397 SkShader::TileMode tileModes[2];
398 SkScalar twoPointParams[3];
399 SkShader::BitmapType bmptype = shader->asABitmap(&bitmap, &matrix,
400 tileModes, twoPointParams);
401
bsalomon@google.com5782d712011-01-21 21:03:59 +0000402 GrSamplerState::SampleMode sampleMode = sk_bmp_type_to_sample_mode[bmptype];
403 if (-1 == sampleMode) {
404 SkDebugf("shader->asABitmap() == kNone_BitmapType\n");
405 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000406 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000407 grPaint->fSampler.setSampleMode(sampleMode);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000408 grPaint->fSampler.setFilter(skPaint.isFilterBitmap());
bsalomon@google.com5782d712011-01-21 21:03:59 +0000409 grPaint->fSampler.setWrapX(sk_tile_mode_to_grwrap(tileModes[0]));
410 grPaint->fSampler.setWrapY(sk_tile_mode_to_grwrap(tileModes[1]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000411
412 if (GrSamplerState::kRadial2_SampleMode == sampleMode) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000413 grPaint->fSampler.setRadial2Params(twoPointParams[0],
414 twoPointParams[1],
415 twoPointParams[2] < 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000416 }
417
bsalomon@google.com5782d712011-01-21 21:03:59 +0000418 GrTexture* texture = act->set(this, bitmap, grPaint->fSampler);
reed@google.comac10a2d2010-12-22 21:39:39 +0000419 if (NULL == texture) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000420 SkDebugf("Couldn't convert bitmap to texture.\n");
421 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000422 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000423 grPaint->setTexture(texture);
reed@google.comac10a2d2010-12-22 21:39:39 +0000424
425 // since our texture coords will be in local space, we wack the texture
426 // matrix to map them back into 0...1 before we load it
427 SkMatrix localM;
428 if (shader->getLocalMatrix(&localM)) {
429 SkMatrix inverse;
430 if (localM.invert(&inverse)) {
431 matrix.preConcat(inverse);
432 }
433 }
434 if (SkShader::kDefault_BitmapType == bmptype) {
435 GrScalar sx = (GR_Scalar1 * texture->contentWidth()) /
436 (bitmap.width() * texture->allocWidth());
437 GrScalar sy = (GR_Scalar1 * texture->contentHeight()) /
438 (bitmap.height() * texture->allocHeight());
439 matrix.postScale(sx, sy);
440
441 } else if (SkShader::kRadial_BitmapType == bmptype) {
442 GrScalar s = (GR_Scalar1 * texture->contentWidth()) /
443 (bitmap.width() * texture->allocWidth());
444 matrix.postScale(s, s);
445 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000446
bsalomon@google.com5782d712011-01-21 21:03:59 +0000447 GrMatrix grmat;
448 SkGr::SkMatrix2GrMatrix(matrix, &grPaint->fTextureMatrix);
449
450 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000451}
452
453///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com5782d712011-01-21 21:03:59 +0000454
455class SkPositionSource {
456public:
457 SkPositionSource(const SkPoint* points, int count)
458 : fPoints(points), fCount(count) {}
459
460 int count() const { return fCount; }
461
462 void writeValue(int i, GrPoint* dstPosition) const {
463 SkASSERT(i < fCount);
464 dstPosition->fX = SkScalarToGrScalar(fPoints[i].fX);
465 dstPosition->fY = SkScalarToGrScalar(fPoints[i].fY);
466 }
467private:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000468 const SkPoint* fPoints;
bsalomon@google.com19628322011-02-03 21:30:17 +0000469 int fCount;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000470};
471
472class SkTexCoordSource {
473public:
474 SkTexCoordSource(const SkPoint* coords)
475 : fCoords(coords) {}
476
477 void writeValue(int i, GrPoint* dstCoord) const {
478 dstCoord->fX = SkScalarToGrScalar(fCoords[i].fX);
479 dstCoord->fY = SkScalarToGrScalar(fCoords[i].fY);
480 }
481private:
482 const SkPoint* fCoords;
483};
484
485class SkColorSource {
486public:
487 SkColorSource(const SkColor* colors) : fColors(colors) {}
488
489 void writeValue(int i, GrColor* dstColor) const {
490 *dstColor = SkGr::SkColor2GrColor(fColors[i]);
491 }
492private:
493 const SkColor* fColors;
494};
495
496class SkIndexSource {
497public:
498 SkIndexSource(const uint16_t* indices, int count)
499 : fIndices(indices), fCount(count) {
500 }
501
502 int count() const { return fCount; }
503
504 void writeValue(int i, uint16_t* dstIndex) const {
505 *dstIndex = fIndices[i];
506 }
507
508private:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000509 const uint16_t* fIndices;
bsalomon@google.com19628322011-02-03 21:30:17 +0000510 int fCount;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000511};
512
513///////////////////////////////////////////////////////////////////////////////
514
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000515#if 0 // not currently being used so don't compile,
516
bsalomon@google.com5782d712011-01-21 21:03:59 +0000517// can be used for positions or texture coordinates
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000518
bsalomon@google.com5782d712011-01-21 21:03:59 +0000519class SkRectFanSource {
520public:
521 SkRectFanSource(const SkRect& rect) : fRect(rect) {}
522
523 int count() const { return 4; }
524
525 void writeValue(int i, GrPoint* dstPoint) const {
526 SkASSERT(i < 4);
527 dstPoint->fX = SkScalarToGrScalar((i % 3) ? fRect.fRight :
528 fRect.fLeft);
529 dstPoint->fY = SkScalarToGrScalar((i < 2) ? fRect.fTop :
530 fRect.fBottom);
531 }
532private:
533 const SkRect& fRect;
534};
535
536class SkIRectFanSource {
537public:
538 SkIRectFanSource(const SkIRect& rect) : fRect(rect) {}
539
540 int count() const { return 4; }
541
542 void writeValue(int i, GrPoint* dstPoint) const {
543 SkASSERT(i < 4);
544 dstPoint->fX = (i % 3) ? GrIntToScalar(fRect.fRight) :
545 GrIntToScalar(fRect.fLeft);
546 dstPoint->fY = (i < 2) ? GrIntToScalar(fRect.fTop) :
547 GrIntToScalar(fRect.fBottom);
548 }
549private:
550 const SkIRect& fRect;
551};
552
553class SkMatRectFanSource {
554public:
555 SkMatRectFanSource(const SkRect& rect, const SkMatrix& matrix)
556 : fRect(rect), fMatrix(matrix) {}
557
558 int count() const { return 4; }
559
560 void writeValue(int i, GrPoint* dstPoint) const {
561 SkASSERT(i < 4);
562
563#if SK_SCALAR_IS_GR_SCALAR
564 fMatrix.mapXY((i % 3) ? fRect.fRight : fRect.fLeft,
565 (i < 2) ? fRect.fTop : fRect.fBottom,
566 (SkPoint*)dstPoint);
567#else
568 SkPoint dst;
569 fMatrix.mapXY((i % 3) ? fRect.fRight : fRect.fLeft,
570 (i < 2) ? fRect.fTop : fRect.fBottom,
571 &dst);
572 dstPoint->fX = SkScalarToGrScalar(dst.fX);
573 dstPoint->fY = SkScalarToGrScalar(dst.fY);
574#endif
575 }
576private:
577 const SkRect& fRect;
578 const SkMatrix& fMatrix;
579};
580
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000581#endif
582
reed@google.comac10a2d2010-12-22 21:39:39 +0000583///////////////////////////////////////////////////////////////////////////////
584
585void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
586 CHECK_SHOULD_DRAW(draw);
587
bsalomon@google.com5782d712011-01-21 21:03:59 +0000588 GrPaint grPaint;
589 SkAutoCachedTexture act;
590 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000591 return;
592 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000593
594 fContext->drawPaint(grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000595}
596
597// must be in SkCanvas::PointMode order
bsalomon@google.com5782d712011-01-21 21:03:59 +0000598static const GrDrawTarget::PrimitiveType gPointMode2PrimtiveType[] = {
599 GrDrawTarget::kPoints_PrimitiveType,
600 GrDrawTarget::kLines_PrimitiveType,
601 GrDrawTarget::kLineStrip_PrimitiveType
reed@google.comac10a2d2010-12-22 21:39:39 +0000602};
603
604void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000605 size_t count, const SkPoint pts[], const SkPaint& paint) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000606 CHECK_SHOULD_DRAW(draw);
607
608 SkScalar width = paint.getStrokeWidth();
609 if (width < 0) {
610 return;
611 }
612
613 // we only handle hairlines here, else we let the SkDraw call our drawPath()
614 if (width > 0) {
615 draw.drawPoints(mode, count, pts, paint, true);
616 return;
617 }
618
bsalomon@google.com5782d712011-01-21 21:03:59 +0000619 GrPaint grPaint;
620 SkAutoCachedTexture act;
621 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000622 return;
623 }
624
reed@google.comac10a2d2010-12-22 21:39:39 +0000625#if SK_SCALAR_IS_GR_SCALAR
bsalomon@google.com5782d712011-01-21 21:03:59 +0000626 fContext->drawVertices(grPaint,
627 gPointMode2PrimtiveType[mode],
628 count,
629 (GrPoint*)pts,
630 NULL,
631 NULL,
632 NULL,
633 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000634#else
bsalomon@google.com5782d712011-01-21 21:03:59 +0000635 fContext->drawCustomVertices(grPaint,
636 gPointMode2PrimtiveType[mode],
637 SkPositionSource(pts, count));
reed@google.comac10a2d2010-12-22 21:39:39 +0000638#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000639}
640
641void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
642 const SkPaint& paint) {
643 CHECK_SHOULD_DRAW(draw);
644
645 bool doStroke = paint.getStyle() == SkPaint::kStroke_Style;
646 SkScalar width = paint.getStrokeWidth();
647
648 /*
649 We have special code for hairline strokes, miter-strokes, and fills.
650 Anything else we just call our path code. (i.e. non-miter thick stroke)
651 */
652 if (doStroke && width > 0 && paint.getStrokeJoin() != SkPaint::kMiter_Join) {
653 SkPath path;
654 path.addRect(rect);
655 this->drawPath(draw, path, paint, NULL, true);
656 return;
657 }
658
bsalomon@google.com5782d712011-01-21 21:03:59 +0000659 GrPaint grPaint;
660 SkAutoCachedTexture act;
661 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000662 return;
663 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000664 fContext->drawRect(grPaint, Sk2Gr(rect), doStroke ? width : -1);
reed@google.comac10a2d2010-12-22 21:39:39 +0000665}
666
667void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& path,
668 const SkPaint& paint, const SkMatrix* prePathMatrix,
669 bool pathIsMutable) {
670 CHECK_SHOULD_DRAW(draw);
671
bsalomon@google.com5782d712011-01-21 21:03:59 +0000672 GrPaint grPaint;
673 SkAutoCachedTexture act;
674 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000675 return;
676 }
677
678 const SkPath* pathPtr = &path;
679 SkPath tmpPath;
680
681 if (prePathMatrix) {
682 if (pathIsMutable) {
683 const_cast<SkPath*>(pathPtr)->transform(*prePathMatrix);
684 } else {
685 path.transform(*prePathMatrix, &tmpPath);
686 pathPtr = &tmpPath;
687 }
688 }
689
690 SkPath fillPath;
691 GrContext::PathFills fill = GrContext::kHairLine_PathFill;
692
693 if (paint.getFillPath(*pathPtr, &fillPath)) {
694 switch (fillPath.getFillType()) {
695 case SkPath::kWinding_FillType:
696 fill = GrContext::kWinding_PathFill;
697 break;
698 case SkPath::kEvenOdd_FillType:
699 fill = GrContext::kEvenOdd_PathFill;
700 break;
701 case SkPath::kInverseWinding_FillType:
702 fill = GrContext::kInverseWinding_PathFill;
703 break;
704 case SkPath::kInverseEvenOdd_FillType:
705 fill = GrContext::kInverseEvenOdd_PathFill;
706 break;
707 default:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000708 SkDebugf("Unsupported path fill type\n");
reed@google.comac10a2d2010-12-22 21:39:39 +0000709 return;
710 }
711 }
712
713 SkGrPathIter iter(fillPath);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000714 fContext->drawPath(grPaint, &iter, fill);
reed@google.comac10a2d2010-12-22 21:39:39 +0000715}
716
reed@google.comac10a2d2010-12-22 21:39:39 +0000717void SkGpuDevice::drawBitmap(const SkDraw& draw,
718 const SkBitmap& bitmap,
719 const SkIRect* srcRectPtr,
720 const SkMatrix& m,
721 const SkPaint& paint) {
722 CHECK_SHOULD_DRAW(draw);
723
724 SkIRect srcRect;
725 if (NULL == srcRectPtr) {
726 srcRect.set(0, 0, bitmap.width(), bitmap.height());
727 } else {
728 srcRect = *srcRectPtr;
729 }
730
bsalomon@google.com5782d712011-01-21 21:03:59 +0000731 GrPaint grPaint;
732 if (!this->skPaint2GrPaintNoShader(paint, true, &grPaint)) {
733 return;
734 }
735 grPaint.fSampler.setFilter(paint.isFilterBitmap());
736
reed@google.com02a7e6c2011-01-28 21:21:49 +0000737 const int maxTextureDim = fContext->getMaxTextureDimension();
738 if (bitmap.getTexture() || (bitmap.width() <= maxTextureDim &&
739 bitmap.height() <= maxTextureDim)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000740 // take the fast case
bsalomon@google.com5782d712011-01-21 21:03:59 +0000741 this->internalDrawBitmap(draw, bitmap, srcRect, m, &grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000742 return;
743 }
744
745 // undo the translate done by SkCanvas
746 int DX = SkMax32(0, srcRect.fLeft);
747 int DY = SkMax32(0, srcRect.fTop);
748 // compute clip bounds in local coordinates
749 SkIRect clipRect;
750 {
751 SkRect r;
752 r.set(draw.fClip->getBounds());
753 SkMatrix matrix, inverse;
754 matrix.setConcat(*draw.fMatrix, m);
755 if (!matrix.invert(&inverse)) {
756 return;
757 }
758 inverse.mapRect(&r);
759 r.roundOut(&clipRect);
760 // apply the canvas' translate to our local clip
761 clipRect.offset(DX, DY);
762 }
763
reed@google.com02a7e6c2011-01-28 21:21:49 +0000764 int nx = bitmap.width() / maxTextureDim;
765 int ny = bitmap.height() / maxTextureDim;
reed@google.comac10a2d2010-12-22 21:39:39 +0000766 for (int x = 0; x <= nx; x++) {
767 for (int y = 0; y <= ny; y++) {
768 SkIRect tileR;
reed@google.com02a7e6c2011-01-28 21:21:49 +0000769 tileR.set(x * maxTextureDim, y * maxTextureDim,
770 (x + 1) * maxTextureDim, (y + 1) * maxTextureDim);
reed@google.comac10a2d2010-12-22 21:39:39 +0000771 if (!SkIRect::Intersects(tileR, clipRect)) {
772 continue;
773 }
774
775 SkIRect srcR = tileR;
776 if (!srcR.intersect(srcRect)) {
777 continue;
778 }
779
780 SkBitmap tmpB;
781 if (bitmap.extractSubset(&tmpB, tileR)) {
782 // now offset it to make it "local" to our tmp bitmap
783 srcR.offset(-tileR.fLeft, -tileR.fTop);
784
785 SkMatrix tmpM(m);
786 {
787 int dx = tileR.fLeft - DX + SkMax32(0, srcR.fLeft);
788 int dy = tileR.fTop - DY + SkMax32(0, srcR.fTop);
789 tmpM.preTranslate(SkIntToScalar(dx), SkIntToScalar(dy));
790 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000791 this->internalDrawBitmap(draw, tmpB, srcR, tmpM, &grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000792 }
793 }
794 }
795}
796
797/*
798 * This is called by drawBitmap(), which has to handle images that may be too
799 * large to be represented by a single texture.
800 *
bsalomon@google.com5782d712011-01-21 21:03:59 +0000801 * internalDrawBitmap assumes that the specified bitmap will fit in a texture
802 * and that non-texture portion of the GrPaint has already been setup.
reed@google.comac10a2d2010-12-22 21:39:39 +0000803 */
804void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
805 const SkBitmap& bitmap,
806 const SkIRect& srcRect,
807 const SkMatrix& m,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000808 GrPaint* grPaint) {
reed@google.com02a7e6c2011-01-28 21:21:49 +0000809 SkASSERT(bitmap.width() <= fContext->getMaxTextureDimension() &&
810 bitmap.height() <= fContext->getMaxTextureDimension());
reed@google.comac10a2d2010-12-22 21:39:39 +0000811
812 SkAutoLockPixels alp(bitmap);
813 if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
814 return;
815 }
816
bsalomon@google.com5782d712011-01-21 21:03:59 +0000817 grPaint->fSampler.setWrapX(GrSamplerState::kClamp_WrapMode);
818 grPaint->fSampler.setWrapY(GrSamplerState::kClamp_WrapMode);
819 grPaint->fSampler.setSampleMode(GrSamplerState::kNormal_SampleMode);
reed@google.comac10a2d2010-12-22 21:39:39 +0000820
821 GrTexture* texture;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000822 SkAutoCachedTexture act(this, bitmap, grPaint->fSampler, &texture);
reed@google.comac10a2d2010-12-22 21:39:39 +0000823 if (NULL == texture) {
824 return;
825 }
826
bsalomon@google.com5782d712011-01-21 21:03:59 +0000827 grPaint->setTexture(texture);
828 grPaint->fTextureMatrix.setIdentity();
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000829 GrRect dstRect(0, 0, GrIntToScalar(srcRect.width()), GrIntToScalar(srcRect.height()));
830 GrRect paintRect(GrIntToScalar(srcRect.fLeft) / texture->allocWidth(),
831 GrIntToScalar(srcRect.fTop) / texture->allocHeight(),
832 GrIntToScalar(srcRect.fRight) / texture->allocWidth(),
833 GrIntToScalar(srcRect.fBottom) / texture->allocHeight());
reed@google.comac10a2d2010-12-22 21:39:39 +0000834
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000835 GrMatrix grMat;
836 SkGr::SkMatrix2GrMatrix(m, &grMat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000837
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000838 fContext->drawRectToRect(*grPaint, dstRect, paintRect, &grMat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000839}
840
841void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
842 int left, int top, const SkPaint& paint) {
843 CHECK_SHOULD_DRAW(draw);
844
845 SkAutoLockPixels alp(bitmap);
846 if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
847 return;
848 }
849
bsalomon@google.com5782d712011-01-21 21:03:59 +0000850 GrPaint grPaint;
851 if(!this->skPaint2GrPaintNoShader(paint, true, &grPaint)) {
852 return;
853 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000854
bsalomon@google.com5782d712011-01-21 21:03:59 +0000855 GrAutoMatrix avm(fContext, GrMatrix::I());
856
857 GrTexture* texture;
858 grPaint.fSampler.setClampNoFilter();
859 SkAutoCachedTexture act(this, bitmap, grPaint.fSampler, &texture);
860
861 grPaint.fTextureMatrix.setIdentity();
862 grPaint.setTexture(texture);
863
864 SkPoint max;
reed@google.comac10a2d2010-12-22 21:39:39 +0000865 max.set(SkFixedToScalar((texture->contentWidth() << 16) /
866 texture->allocWidth()),
867 SkFixedToScalar((texture->contentHeight() << 16) /
868 texture->allocHeight()));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000869
870 fContext->drawRectToRect(grPaint,
871 GrRect(GrIntToScalar(left), GrIntToScalar(top),
872 GrIntToScalar(left + bitmap.width()),
873 GrIntToScalar(top + bitmap.height())),
874 GrRect(0, 0, max.fX, max.fY));
reed@google.comac10a2d2010-12-22 21:39:39 +0000875}
876
877void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* dev,
878 int x, int y, const SkPaint& paint) {
879 CHECK_SHOULD_DRAW(draw);
880
881 SkPoint max;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000882 GrPaint grPaint;
883 if (!((SkGpuDevice*)dev)->bindDeviceAsTexture(&grPaint, &max) ||
884 !this->skPaint2GrPaintNoShader(paint, true, &grPaint)) {
885 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000886 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000887
888 SkASSERT(NULL != grPaint.getTexture());
889
890 const SkBitmap& bm = dev->accessBitmap(false);
891 int w = bm.width();
892 int h = bm.height();
893
894 GrAutoMatrix avm(fContext, GrMatrix::I());
895
896 grPaint.fSampler.setClampNoFilter();
897 grPaint.fTextureMatrix.setIdentity();
898
899 fContext->drawRectToRect(grPaint,
reed@google.com1a2e8d22011-01-21 22:08:29 +0000900 GrRect(GrIntToScalar(x),
901 GrIntToScalar(y),
902 GrIntToScalar(x + w),
bsalomon@google.com5782d712011-01-21 21:03:59 +0000903 GrIntToScalar(y + h)),
reed@google.com1a2e8d22011-01-21 22:08:29 +0000904 GrRect(0,
905 0,
906 GrIntToScalar(max.fX),
bsalomon@google.com5782d712011-01-21 21:03:59 +0000907 GrIntToScalar(max.fY)));
reed@google.comac10a2d2010-12-22 21:39:39 +0000908}
909
910///////////////////////////////////////////////////////////////////////////////
911
912// must be in SkCanvas::VertexMode order
bsalomon@google.com5782d712011-01-21 21:03:59 +0000913static const GrDrawTarget::PrimitiveType gVertexMode2PrimitiveType[] = {
914 GrDrawTarget::kTriangles_PrimitiveType,
915 GrDrawTarget::kTriangleStrip_PrimitiveType,
916 GrDrawTarget::kTriangleFan_PrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +0000917};
918
919void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
920 int vertexCount, const SkPoint vertices[],
921 const SkPoint texs[], const SkColor colors[],
922 SkXfermode* xmode,
923 const uint16_t indices[], int indexCount,
924 const SkPaint& paint) {
925 CHECK_SHOULD_DRAW(draw);
926
bsalomon@google.com5782d712011-01-21 21:03:59 +0000927 GrPaint grPaint;
928 SkAutoCachedTexture act;
929 // we ignore the shader if texs is null.
930 if (NULL == texs) {
931 if (!this->skPaint2GrPaintNoShader(paint, false, &grPaint)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000932 return;
933 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000934 } else {
reed@google.com1a2e8d22011-01-21 22:08:29 +0000935 if (!this->skPaint2GrPaintShader(paint, &act,
936 *draw.fMatrix,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000937 &grPaint)) {
938 return;
939 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000940 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000941
942 if (NULL != xmode && NULL != texs && NULL != colors) {
943 SkXfermode::Mode mode;
944 if (!SkXfermode::IsMode(xmode, &mode) ||
945 SkXfermode::kMultiply_Mode != mode) {
946 SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
947#if 0
948 return
949#endif
950 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000951 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000952
953#if SK_SCALAR_IS_GR_SCALAR
954 // even if GrColor and SkColor byte offsets match we need
955 // to perform pre-multiply.
956 if (NULL == colors) {
957 fContext->drawVertices(grPaint,
958 gVertexMode2PrimitiveType[vmode],
959 vertexCount,
960 (GrPoint*) vertices,
961 (GrPoint*) texs,
962 NULL,
963 indices,
964 indexCount);
965 } else
966#endif
967 {
968 SkTexCoordSource texSrc(texs);
969 SkColorSource colSrc(colors);
970 SkIndexSource idxSrc(indices, indexCount);
971
972 fContext->drawCustomVertices(grPaint,
973 gVertexMode2PrimitiveType[vmode],
974 SkPositionSource(vertices, vertexCount),
975 (NULL == texs) ? NULL : &texSrc,
976 (NULL == colors) ? NULL : &colSrc,
977 (NULL == indices) ? NULL : &idxSrc);
reed@google.comac10a2d2010-12-22 21:39:39 +0000978 }
979}
980
981///////////////////////////////////////////////////////////////////////////////
982
983static void GlyphCacheAuxProc(void* data) {
984 delete (GrFontScaler*)data;
985}
986
987static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
988 void* auxData;
989 GrFontScaler* scaler = NULL;
990 if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
991 scaler = (GrFontScaler*)auxData;
992 }
993 if (NULL == scaler) {
994 scaler = new SkGrFontScaler(cache);
995 cache->setAuxProc(GlyphCacheAuxProc, scaler);
996 }
997 return scaler;
998}
999
1000static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
1001 SkFixed fx, SkFixed fy,
1002 const SkGlyph& glyph) {
1003 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1004
1005 GrSkDrawProcs* procs = (GrSkDrawProcs*)state.fDraw->fProcs;
1006
1007 if (NULL == procs->fFontScaler) {
1008 procs->fFontScaler = get_gr_font_scaler(state.fCache);
1009 }
1010 procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), fx, 0),
1011 SkIntToFixed(SkFixedFloor(fx)), fy,
1012 procs->fFontScaler);
1013}
1014
bsalomon@google.com5782d712011-01-21 21:03:59 +00001015SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001016
1017 // deferred allocation
1018 if (NULL == fDrawProcs) {
1019 fDrawProcs = new GrSkDrawProcs;
1020 fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
1021 fDrawProcs->fContext = fContext;
1022 }
1023
1024 // init our (and GL's) state
1025 fDrawProcs->fTextContext = context;
1026 fDrawProcs->fFontScaler = NULL;
1027 return fDrawProcs;
1028}
1029
1030void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
1031 size_t byteLength, SkScalar x, SkScalar y,
1032 const SkPaint& paint) {
1033 CHECK_SHOULD_DRAW(draw);
1034
1035 if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1036 // this guy will just call our drawPath()
1037 draw.drawText((const char*)text, byteLength, x, y, paint);
1038 } else {
1039 SkAutoExtMatrix aem(draw.fExtMatrix);
1040 SkDraw myDraw(draw);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001041
1042 GrPaint grPaint;
1043 SkAutoCachedTexture act;
1044
1045 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
1046 return;
1047 }
1048 GrTextContext context(fContext, grPaint, aem.extMatrix());
1049 myDraw.fProcs = this->initDrawForText(&context);
reed@google.comac10a2d2010-12-22 21:39:39 +00001050 this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
1051 }
1052}
1053
1054void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
1055 size_t byteLength, const SkScalar pos[],
1056 SkScalar constY, int scalarsPerPos,
1057 const SkPaint& paint) {
1058 CHECK_SHOULD_DRAW(draw);
1059
1060 if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1061 // this guy will just call our drawPath()
1062 draw.drawPosText((const char*)text, byteLength, pos, constY,
1063 scalarsPerPos, paint);
1064 } else {
1065 SkAutoExtMatrix aem(draw.fExtMatrix);
1066 SkDraw myDraw(draw);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001067
1068 GrPaint grPaint;
1069 SkAutoCachedTexture act;
1070 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
1071 return;
1072 }
1073
1074 GrTextContext context(fContext, grPaint, aem.extMatrix());
1075 myDraw.fProcs = this->initDrawForText(&context);
reed@google.comac10a2d2010-12-22 21:39:39 +00001076 this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
1077 scalarsPerPos, paint);
1078 }
1079}
1080
1081void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
1082 size_t len, const SkPath& path,
1083 const SkMatrix* m, const SkPaint& paint) {
1084 CHECK_SHOULD_DRAW(draw);
1085
1086 SkASSERT(draw.fDevice == this);
1087 draw.drawTextOnPath((const char*)text, len, path, m, paint);
1088}
1089
1090///////////////////////////////////////////////////////////////////////////////
1091
1092SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
1093 const GrSamplerState& sampler,
1094 GrTexture** texture,
1095 bool forDeviceRenderTarget) {
1096 GrContext* ctx = this->context();
1097 uint32_t p0, p1;
1098 if (forDeviceRenderTarget) {
1099 p0 = p1 = -1;
1100 } else {
1101 p0 = bitmap.getGenerationID();
1102 p1 = bitmap.pixelRefOffset();
1103 }
1104
1105 GrTexture* newTexture = NULL;
1106 GrTextureKey key(p0, p1, bitmap.width(), bitmap.height());
1107 GrTextureEntry* entry = ctx->findAndLockTexture(&key, sampler);
1108
1109 if (NULL == entry) {
1110
1111 if (forDeviceRenderTarget) {
1112 const GrGpu::TextureDesc desc = {
1113 GrGpu::kRenderTarget_TextureFlag,
1114 GrGpu::kNone_AALevel,
1115 bitmap.width(),
1116 bitmap.height(),
1117 SkGr::Bitmap2PixelConfig(bitmap)
1118 };
1119 entry = ctx->createAndLockTexture(&key, sampler, desc, NULL, 0);
1120
1121 } else {
1122 entry = sk_gr_create_bitmap_texture(ctx, &key, sampler, bitmap);
1123 }
1124 if (NULL == entry) {
1125 GrPrintf("---- failed to create texture for cache [%d %d]\n",
1126 bitmap.width(), bitmap.height());
1127 }
1128 }
1129
1130 if (NULL != entry) {
1131 newTexture = entry->texture();
reed@google.comac10a2d2010-12-22 21:39:39 +00001132 if (texture) {
1133 *texture = newTexture;
1134 }
1135 // IMPORTANT: We can't allow another SkGpuDevice to get this
1136 // cache entry until this one is destroyed!
1137 if (forDeviceRenderTarget) {
1138 ctx->detachCachedTexture(entry);
1139 }
1140 }
1141 return (TexCache*)entry;
1142}
1143
1144void SkGpuDevice::unlockCachedTexture(TexCache* cache) {
1145 this->context()->unlockTexture((GrTextureEntry*)cache);
1146}
1147
reed@google.com7b201d22011-01-11 18:59:23 +00001148///////////////////////////////////////////////////////////////////////////////
1149
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001150SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context,
1151 GrRenderTarget* rootRenderTarget)
1152 : fContext(context) {
1153
1154 GrAssert(NULL != context);
1155 GrAssert(NULL != rootRenderTarget);
1156
1157 // check this now rather than passing this value to SkGpuDevice cons.
1158 // we want the rt that is bound *now* in the 3D API, not the one
1159 // at the time of newDevice.
1160 if (SkGpuDevice::Current3DApiRenderTarget() == rootRenderTarget) {
1161 fRootRenderTarget = context->createRenderTargetFrom3DApiState();
1162 } else {
1163 fRootRenderTarget = rootRenderTarget;
1164 rootRenderTarget->ref();
1165 }
reed@google.com7b201d22011-01-11 18:59:23 +00001166 context->ref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001167
reed@google.com7b201d22011-01-11 18:59:23 +00001168}
1169
1170SkGpuDeviceFactory::~SkGpuDeviceFactory() {
1171 fContext->unref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001172 fRootRenderTarget->unref();
reed@google.com7b201d22011-01-11 18:59:23 +00001173}
1174
1175SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
1176 int width, int height,
1177 bool isOpaque, bool isLayer) {
1178 SkBitmap bm;
1179 bm.setConfig(config, width, height);
1180 bm.setIsOpaque(isOpaque);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001181 return new SkGpuDevice(fContext, bm, isLayer ? NULL : fRootRenderTarget);
reed@google.com7b201d22011-01-11 18:59:23 +00001182}
reed@google.comac10a2d2010-12-22 21:39:39 +00001183