blob: dca146ec5f99be6122cb40aed3a87be010b49406 [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);
reed@google.comac10a2d2010-12-22 21:39:39 +0000408
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:
468 int fCount;
469 const SkPoint* fPoints;
470};
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:
509 int fCount;
510 const uint16_t* fIndices;
511};
512
513///////////////////////////////////////////////////////////////////////////////
514
515// can be used for positions or texture coordinates
516class SkRectFanSource {
517public:
518 SkRectFanSource(const SkRect& rect) : fRect(rect) {}
519
520 int count() const { return 4; }
521
522 void writeValue(int i, GrPoint* dstPoint) const {
523 SkASSERT(i < 4);
524 dstPoint->fX = SkScalarToGrScalar((i % 3) ? fRect.fRight :
525 fRect.fLeft);
526 dstPoint->fY = SkScalarToGrScalar((i < 2) ? fRect.fTop :
527 fRect.fBottom);
528 }
529private:
530 const SkRect& fRect;
531};
532
533class SkIRectFanSource {
534public:
535 SkIRectFanSource(const SkIRect& rect) : fRect(rect) {}
536
537 int count() const { return 4; }
538
539 void writeValue(int i, GrPoint* dstPoint) const {
540 SkASSERT(i < 4);
541 dstPoint->fX = (i % 3) ? GrIntToScalar(fRect.fRight) :
542 GrIntToScalar(fRect.fLeft);
543 dstPoint->fY = (i < 2) ? GrIntToScalar(fRect.fTop) :
544 GrIntToScalar(fRect.fBottom);
545 }
546private:
547 const SkIRect& fRect;
548};
549
550class SkMatRectFanSource {
551public:
552 SkMatRectFanSource(const SkRect& rect, const SkMatrix& matrix)
553 : fRect(rect), fMatrix(matrix) {}
554
555 int count() const { return 4; }
556
557 void writeValue(int i, GrPoint* dstPoint) const {
558 SkASSERT(i < 4);
559
560#if SK_SCALAR_IS_GR_SCALAR
561 fMatrix.mapXY((i % 3) ? fRect.fRight : fRect.fLeft,
562 (i < 2) ? fRect.fTop : fRect.fBottom,
563 (SkPoint*)dstPoint);
564#else
565 SkPoint dst;
566 fMatrix.mapXY((i % 3) ? fRect.fRight : fRect.fLeft,
567 (i < 2) ? fRect.fTop : fRect.fBottom,
568 &dst);
569 dstPoint->fX = SkScalarToGrScalar(dst.fX);
570 dstPoint->fY = SkScalarToGrScalar(dst.fY);
571#endif
572 }
573private:
574 const SkRect& fRect;
575 const SkMatrix& fMatrix;
576};
577
reed@google.comac10a2d2010-12-22 21:39:39 +0000578///////////////////////////////////////////////////////////////////////////////
579
580void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
581 CHECK_SHOULD_DRAW(draw);
582
bsalomon@google.com5782d712011-01-21 21:03:59 +0000583 GrPaint grPaint;
584 SkAutoCachedTexture act;
585 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000586 return;
587 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000588
589 fContext->drawPaint(grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000590}
591
592// must be in SkCanvas::PointMode order
bsalomon@google.com5782d712011-01-21 21:03:59 +0000593static const GrDrawTarget::PrimitiveType gPointMode2PrimtiveType[] = {
594 GrDrawTarget::kPoints_PrimitiveType,
595 GrDrawTarget::kLines_PrimitiveType,
596 GrDrawTarget::kLineStrip_PrimitiveType
reed@google.comac10a2d2010-12-22 21:39:39 +0000597};
598
599void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000600 size_t count, const SkPoint pts[], const SkPaint& paint) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000601 CHECK_SHOULD_DRAW(draw);
602
603 SkScalar width = paint.getStrokeWidth();
604 if (width < 0) {
605 return;
606 }
607
608 // we only handle hairlines here, else we let the SkDraw call our drawPath()
609 if (width > 0) {
610 draw.drawPoints(mode, count, pts, paint, true);
611 return;
612 }
613
bsalomon@google.com5782d712011-01-21 21:03:59 +0000614 GrPaint grPaint;
615 SkAutoCachedTexture act;
616 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000617 return;
618 }
619
reed@google.comac10a2d2010-12-22 21:39:39 +0000620#if SK_SCALAR_IS_GR_SCALAR
bsalomon@google.com5782d712011-01-21 21:03:59 +0000621 fContext->drawVertices(grPaint,
622 gPointMode2PrimtiveType[mode],
623 count,
624 (GrPoint*)pts,
625 NULL,
626 NULL,
627 NULL,
628 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000629#else
bsalomon@google.com5782d712011-01-21 21:03:59 +0000630 fContext->drawCustomVertices(grPaint,
631 gPointMode2PrimtiveType[mode],
632 SkPositionSource(pts, count));
reed@google.comac10a2d2010-12-22 21:39:39 +0000633#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000634}
635
636void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
637 const SkPaint& paint) {
638 CHECK_SHOULD_DRAW(draw);
639
640 bool doStroke = paint.getStyle() == SkPaint::kStroke_Style;
641 SkScalar width = paint.getStrokeWidth();
642
643 /*
644 We have special code for hairline strokes, miter-strokes, and fills.
645 Anything else we just call our path code. (i.e. non-miter thick stroke)
646 */
647 if (doStroke && width > 0 && paint.getStrokeJoin() != SkPaint::kMiter_Join) {
648 SkPath path;
649 path.addRect(rect);
650 this->drawPath(draw, path, paint, NULL, true);
651 return;
652 }
653
bsalomon@google.com5782d712011-01-21 21:03:59 +0000654 GrPaint grPaint;
655 SkAutoCachedTexture act;
656 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000657 return;
658 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000659 fContext->drawRect(grPaint, Sk2Gr(rect), doStroke ? width : -1);
reed@google.comac10a2d2010-12-22 21:39:39 +0000660}
661
662void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& path,
663 const SkPaint& paint, const SkMatrix* prePathMatrix,
664 bool pathIsMutable) {
665 CHECK_SHOULD_DRAW(draw);
666
bsalomon@google.com5782d712011-01-21 21:03:59 +0000667 GrPaint grPaint;
668 SkAutoCachedTexture act;
669 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000670 return;
671 }
672
673 const SkPath* pathPtr = &path;
674 SkPath tmpPath;
675
676 if (prePathMatrix) {
677 if (pathIsMutable) {
678 const_cast<SkPath*>(pathPtr)->transform(*prePathMatrix);
679 } else {
680 path.transform(*prePathMatrix, &tmpPath);
681 pathPtr = &tmpPath;
682 }
683 }
684
685 SkPath fillPath;
686 GrContext::PathFills fill = GrContext::kHairLine_PathFill;
687
688 if (paint.getFillPath(*pathPtr, &fillPath)) {
689 switch (fillPath.getFillType()) {
690 case SkPath::kWinding_FillType:
691 fill = GrContext::kWinding_PathFill;
692 break;
693 case SkPath::kEvenOdd_FillType:
694 fill = GrContext::kEvenOdd_PathFill;
695 break;
696 case SkPath::kInverseWinding_FillType:
697 fill = GrContext::kInverseWinding_PathFill;
698 break;
699 case SkPath::kInverseEvenOdd_FillType:
700 fill = GrContext::kInverseEvenOdd_PathFill;
701 break;
702 default:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000703 SkDebugf("Unsupported path fill type\n");
reed@google.comac10a2d2010-12-22 21:39:39 +0000704 return;
705 }
706 }
707
708 SkGrPathIter iter(fillPath);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000709 fContext->drawPath(grPaint, &iter, fill);
reed@google.comac10a2d2010-12-22 21:39:39 +0000710}
711
reed@google.comac10a2d2010-12-22 21:39:39 +0000712void SkGpuDevice::drawBitmap(const SkDraw& draw,
713 const SkBitmap& bitmap,
714 const SkIRect* srcRectPtr,
715 const SkMatrix& m,
716 const SkPaint& paint) {
717 CHECK_SHOULD_DRAW(draw);
718
719 SkIRect srcRect;
720 if (NULL == srcRectPtr) {
721 srcRect.set(0, 0, bitmap.width(), bitmap.height());
722 } else {
723 srcRect = *srcRectPtr;
724 }
725
bsalomon@google.com5782d712011-01-21 21:03:59 +0000726 GrPaint grPaint;
727 if (!this->skPaint2GrPaintNoShader(paint, true, &grPaint)) {
728 return;
729 }
730 grPaint.fSampler.setFilter(paint.isFilterBitmap());
731
reed@google.com02a7e6c2011-01-28 21:21:49 +0000732 const int maxTextureDim = fContext->getMaxTextureDimension();
733 if (bitmap.getTexture() || (bitmap.width() <= maxTextureDim &&
734 bitmap.height() <= maxTextureDim)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000735 // take the fast case
bsalomon@google.com5782d712011-01-21 21:03:59 +0000736 this->internalDrawBitmap(draw, bitmap, srcRect, m, &grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000737 return;
738 }
739
740 // undo the translate done by SkCanvas
741 int DX = SkMax32(0, srcRect.fLeft);
742 int DY = SkMax32(0, srcRect.fTop);
743 // compute clip bounds in local coordinates
744 SkIRect clipRect;
745 {
746 SkRect r;
747 r.set(draw.fClip->getBounds());
748 SkMatrix matrix, inverse;
749 matrix.setConcat(*draw.fMatrix, m);
750 if (!matrix.invert(&inverse)) {
751 return;
752 }
753 inverse.mapRect(&r);
754 r.roundOut(&clipRect);
755 // apply the canvas' translate to our local clip
756 clipRect.offset(DX, DY);
757 }
758
reed@google.com02a7e6c2011-01-28 21:21:49 +0000759 int nx = bitmap.width() / maxTextureDim;
760 int ny = bitmap.height() / maxTextureDim;
reed@google.comac10a2d2010-12-22 21:39:39 +0000761 for (int x = 0; x <= nx; x++) {
762 for (int y = 0; y <= ny; y++) {
763 SkIRect tileR;
reed@google.com02a7e6c2011-01-28 21:21:49 +0000764 tileR.set(x * maxTextureDim, y * maxTextureDim,
765 (x + 1) * maxTextureDim, (y + 1) * maxTextureDim);
reed@google.comac10a2d2010-12-22 21:39:39 +0000766 if (!SkIRect::Intersects(tileR, clipRect)) {
767 continue;
768 }
769
770 SkIRect srcR = tileR;
771 if (!srcR.intersect(srcRect)) {
772 continue;
773 }
774
775 SkBitmap tmpB;
776 if (bitmap.extractSubset(&tmpB, tileR)) {
777 // now offset it to make it "local" to our tmp bitmap
778 srcR.offset(-tileR.fLeft, -tileR.fTop);
779
780 SkMatrix tmpM(m);
781 {
782 int dx = tileR.fLeft - DX + SkMax32(0, srcR.fLeft);
783 int dy = tileR.fTop - DY + SkMax32(0, srcR.fTop);
784 tmpM.preTranslate(SkIntToScalar(dx), SkIntToScalar(dy));
785 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000786 this->internalDrawBitmap(draw, tmpB, srcR, tmpM, &grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000787 }
788 }
789 }
790}
791
792/*
793 * This is called by drawBitmap(), which has to handle images that may be too
794 * large to be represented by a single texture.
795 *
bsalomon@google.com5782d712011-01-21 21:03:59 +0000796 * internalDrawBitmap assumes that the specified bitmap will fit in a texture
797 * and that non-texture portion of the GrPaint has already been setup.
reed@google.comac10a2d2010-12-22 21:39:39 +0000798 */
799void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
800 const SkBitmap& bitmap,
801 const SkIRect& srcRect,
802 const SkMatrix& m,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000803 GrPaint* grPaint) {
reed@google.com02a7e6c2011-01-28 21:21:49 +0000804 SkASSERT(bitmap.width() <= fContext->getMaxTextureDimension() &&
805 bitmap.height() <= fContext->getMaxTextureDimension());
reed@google.comac10a2d2010-12-22 21:39:39 +0000806
807 SkAutoLockPixels alp(bitmap);
808 if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
809 return;
810 }
811
bsalomon@google.com5782d712011-01-21 21:03:59 +0000812 grPaint->fSampler.setWrapX(GrSamplerState::kClamp_WrapMode);
813 grPaint->fSampler.setWrapY(GrSamplerState::kClamp_WrapMode);
814 grPaint->fSampler.setSampleMode(GrSamplerState::kNormal_SampleMode);
reed@google.comac10a2d2010-12-22 21:39:39 +0000815
816 GrTexture* texture;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000817 SkAutoCachedTexture act(this, bitmap, grPaint->fSampler, &texture);
reed@google.comac10a2d2010-12-22 21:39:39 +0000818 if (NULL == texture) {
819 return;
820 }
821
bsalomon@google.com5782d712011-01-21 21:03:59 +0000822 grPaint->setTexture(texture);
823 grPaint->fTextureMatrix.setIdentity();
reed@google.comac10a2d2010-12-22 21:39:39 +0000824
bsalomon@google.com5782d712011-01-21 21:03:59 +0000825 SkRect paintRect;
826 paintRect.set(SkFixedToScalar((srcRect.fLeft << 16) / texture->allocWidth()),
827 SkFixedToScalar((srcRect.fTop << 16) / texture->allocHeight()),
828 SkFixedToScalar((srcRect.fRight << 16) / texture->allocWidth()),
829 SkFixedToScalar((srcRect.fBottom << 16)/ texture->allocHeight()));
reed@google.comac10a2d2010-12-22 21:39:39 +0000830
bsalomon@google.com5782d712011-01-21 21:03:59 +0000831 SkRect dstRect;
reed@google.com1a2e8d22011-01-21 22:08:29 +0000832 dstRect.set(SkIntToScalar(0),SkIntToScalar(0),
bsalomon@google.com5782d712011-01-21 21:03:59 +0000833 SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
reed@google.comac10a2d2010-12-22 21:39:39 +0000834
bsalomon@google.com5782d712011-01-21 21:03:59 +0000835 SkRectFanSource texSrc(paintRect);
836 fContext->drawCustomVertices(*grPaint,
837 GrDrawTarget::kTriangleFan_PrimitiveType,
838 SkMatRectFanSource(dstRect, m),
839 &texSrc);
reed@google.comac10a2d2010-12-22 21:39:39 +0000840
reed@google.comac10a2d2010-12-22 21:39:39 +0000841}
842
843void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
844 int left, int top, const SkPaint& paint) {
845 CHECK_SHOULD_DRAW(draw);
846
847 SkAutoLockPixels alp(bitmap);
848 if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
849 return;
850 }
851
bsalomon@google.com5782d712011-01-21 21:03:59 +0000852 GrPaint grPaint;
853 if(!this->skPaint2GrPaintNoShader(paint, true, &grPaint)) {
854 return;
855 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000856
bsalomon@google.com5782d712011-01-21 21:03:59 +0000857 GrAutoMatrix avm(fContext, GrMatrix::I());
858
859 GrTexture* texture;
860 grPaint.fSampler.setClampNoFilter();
861 SkAutoCachedTexture act(this, bitmap, grPaint.fSampler, &texture);
862
863 grPaint.fTextureMatrix.setIdentity();
864 grPaint.setTexture(texture);
865
866 SkPoint max;
reed@google.comac10a2d2010-12-22 21:39:39 +0000867 max.set(SkFixedToScalar((texture->contentWidth() << 16) /
868 texture->allocWidth()),
869 SkFixedToScalar((texture->contentHeight() << 16) /
870 texture->allocHeight()));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000871
872 fContext->drawRectToRect(grPaint,
873 GrRect(GrIntToScalar(left), GrIntToScalar(top),
874 GrIntToScalar(left + bitmap.width()),
875 GrIntToScalar(top + bitmap.height())),
876 GrRect(0, 0, max.fX, max.fY));
reed@google.comac10a2d2010-12-22 21:39:39 +0000877}
878
879void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* dev,
880 int x, int y, const SkPaint& paint) {
881 CHECK_SHOULD_DRAW(draw);
882
883 SkPoint max;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000884 GrPaint grPaint;
885 if (!((SkGpuDevice*)dev)->bindDeviceAsTexture(&grPaint, &max) ||
886 !this->skPaint2GrPaintNoShader(paint, true, &grPaint)) {
887 return;
reed@google.comac10a2d2010-12-22 21:39:39 +0000888 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000889
890 SkASSERT(NULL != grPaint.getTexture());
891
892 const SkBitmap& bm = dev->accessBitmap(false);
893 int w = bm.width();
894 int h = bm.height();
895
896 GrAutoMatrix avm(fContext, GrMatrix::I());
897
898 grPaint.fSampler.setClampNoFilter();
899 grPaint.fTextureMatrix.setIdentity();
900
901 fContext->drawRectToRect(grPaint,
reed@google.com1a2e8d22011-01-21 22:08:29 +0000902 GrRect(GrIntToScalar(x),
903 GrIntToScalar(y),
904 GrIntToScalar(x + w),
bsalomon@google.com5782d712011-01-21 21:03:59 +0000905 GrIntToScalar(y + h)),
reed@google.com1a2e8d22011-01-21 22:08:29 +0000906 GrRect(0,
907 0,
908 GrIntToScalar(max.fX),
bsalomon@google.com5782d712011-01-21 21:03:59 +0000909 GrIntToScalar(max.fY)));
reed@google.comac10a2d2010-12-22 21:39:39 +0000910}
911
912///////////////////////////////////////////////////////////////////////////////
913
914// must be in SkCanvas::VertexMode order
bsalomon@google.com5782d712011-01-21 21:03:59 +0000915static const GrDrawTarget::PrimitiveType gVertexMode2PrimitiveType[] = {
916 GrDrawTarget::kTriangles_PrimitiveType,
917 GrDrawTarget::kTriangleStrip_PrimitiveType,
918 GrDrawTarget::kTriangleFan_PrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +0000919};
920
921void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
922 int vertexCount, const SkPoint vertices[],
923 const SkPoint texs[], const SkColor colors[],
924 SkXfermode* xmode,
925 const uint16_t indices[], int indexCount,
926 const SkPaint& paint) {
927 CHECK_SHOULD_DRAW(draw);
928
bsalomon@google.com5782d712011-01-21 21:03:59 +0000929 GrPaint grPaint;
930 SkAutoCachedTexture act;
931 // we ignore the shader if texs is null.
932 if (NULL == texs) {
933 if (!this->skPaint2GrPaintNoShader(paint, false, &grPaint)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000934 return;
935 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000936 } else {
reed@google.com1a2e8d22011-01-21 22:08:29 +0000937 if (!this->skPaint2GrPaintShader(paint, &act,
938 *draw.fMatrix,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000939 &grPaint)) {
940 return;
941 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000942 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000943
944 if (NULL != xmode && NULL != texs && NULL != colors) {
945 SkXfermode::Mode mode;
946 if (!SkXfermode::IsMode(xmode, &mode) ||
947 SkXfermode::kMultiply_Mode != mode) {
948 SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
949#if 0
950 return
951#endif
952 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000953 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000954
955#if SK_SCALAR_IS_GR_SCALAR
956 // even if GrColor and SkColor byte offsets match we need
957 // to perform pre-multiply.
958 if (NULL == colors) {
959 fContext->drawVertices(grPaint,
960 gVertexMode2PrimitiveType[vmode],
961 vertexCount,
962 (GrPoint*) vertices,
963 (GrPoint*) texs,
964 NULL,
965 indices,
966 indexCount);
967 } else
968#endif
969 {
970 SkTexCoordSource texSrc(texs);
971 SkColorSource colSrc(colors);
972 SkIndexSource idxSrc(indices, indexCount);
973
974 fContext->drawCustomVertices(grPaint,
975 gVertexMode2PrimitiveType[vmode],
976 SkPositionSource(vertices, vertexCount),
977 (NULL == texs) ? NULL : &texSrc,
978 (NULL == colors) ? NULL : &colSrc,
979 (NULL == indices) ? NULL : &idxSrc);
reed@google.comac10a2d2010-12-22 21:39:39 +0000980 }
981}
982
983///////////////////////////////////////////////////////////////////////////////
984
985static void GlyphCacheAuxProc(void* data) {
986 delete (GrFontScaler*)data;
987}
988
989static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
990 void* auxData;
991 GrFontScaler* scaler = NULL;
992 if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
993 scaler = (GrFontScaler*)auxData;
994 }
995 if (NULL == scaler) {
996 scaler = new SkGrFontScaler(cache);
997 cache->setAuxProc(GlyphCacheAuxProc, scaler);
998 }
999 return scaler;
1000}
1001
1002static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
1003 SkFixed fx, SkFixed fy,
1004 const SkGlyph& glyph) {
1005 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1006
1007 GrSkDrawProcs* procs = (GrSkDrawProcs*)state.fDraw->fProcs;
1008
1009 if (NULL == procs->fFontScaler) {
1010 procs->fFontScaler = get_gr_font_scaler(state.fCache);
1011 }
1012 procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), fx, 0),
1013 SkIntToFixed(SkFixedFloor(fx)), fy,
1014 procs->fFontScaler);
1015}
1016
bsalomon@google.com5782d712011-01-21 21:03:59 +00001017SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001018
1019 // deferred allocation
1020 if (NULL == fDrawProcs) {
1021 fDrawProcs = new GrSkDrawProcs;
1022 fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
1023 fDrawProcs->fContext = fContext;
1024 }
1025
1026 // init our (and GL's) state
1027 fDrawProcs->fTextContext = context;
1028 fDrawProcs->fFontScaler = NULL;
1029 return fDrawProcs;
1030}
1031
1032void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
1033 size_t byteLength, SkScalar x, SkScalar y,
1034 const SkPaint& paint) {
1035 CHECK_SHOULD_DRAW(draw);
1036
1037 if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1038 // this guy will just call our drawPath()
1039 draw.drawText((const char*)text, byteLength, x, y, paint);
1040 } else {
1041 SkAutoExtMatrix aem(draw.fExtMatrix);
1042 SkDraw myDraw(draw);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001043
1044 GrPaint grPaint;
1045 SkAutoCachedTexture act;
1046
1047 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
1048 return;
1049 }
1050 GrTextContext context(fContext, grPaint, aem.extMatrix());
1051 myDraw.fProcs = this->initDrawForText(&context);
reed@google.comac10a2d2010-12-22 21:39:39 +00001052 this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
1053 }
1054}
1055
1056void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
1057 size_t byteLength, const SkScalar pos[],
1058 SkScalar constY, int scalarsPerPos,
1059 const SkPaint& paint) {
1060 CHECK_SHOULD_DRAW(draw);
1061
1062 if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1063 // this guy will just call our drawPath()
1064 draw.drawPosText((const char*)text, byteLength, pos, constY,
1065 scalarsPerPos, paint);
1066 } else {
1067 SkAutoExtMatrix aem(draw.fExtMatrix);
1068 SkDraw myDraw(draw);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001069
1070 GrPaint grPaint;
1071 SkAutoCachedTexture act;
1072 if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
1073 return;
1074 }
1075
1076 GrTextContext context(fContext, grPaint, aem.extMatrix());
1077 myDraw.fProcs = this->initDrawForText(&context);
reed@google.comac10a2d2010-12-22 21:39:39 +00001078 this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
1079 scalarsPerPos, paint);
1080 }
1081}
1082
1083void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
1084 size_t len, const SkPath& path,
1085 const SkMatrix* m, const SkPaint& paint) {
1086 CHECK_SHOULD_DRAW(draw);
1087
1088 SkASSERT(draw.fDevice == this);
1089 draw.drawTextOnPath((const char*)text, len, path, m, paint);
1090}
1091
1092///////////////////////////////////////////////////////////////////////////////
1093
1094SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
1095 const GrSamplerState& sampler,
1096 GrTexture** texture,
1097 bool forDeviceRenderTarget) {
1098 GrContext* ctx = this->context();
1099 uint32_t p0, p1;
1100 if (forDeviceRenderTarget) {
1101 p0 = p1 = -1;
1102 } else {
1103 p0 = bitmap.getGenerationID();
1104 p1 = bitmap.pixelRefOffset();
1105 }
1106
1107 GrTexture* newTexture = NULL;
1108 GrTextureKey key(p0, p1, bitmap.width(), bitmap.height());
1109 GrTextureEntry* entry = ctx->findAndLockTexture(&key, sampler);
1110
1111 if (NULL == entry) {
1112
1113 if (forDeviceRenderTarget) {
1114 const GrGpu::TextureDesc desc = {
1115 GrGpu::kRenderTarget_TextureFlag,
1116 GrGpu::kNone_AALevel,
1117 bitmap.width(),
1118 bitmap.height(),
1119 SkGr::Bitmap2PixelConfig(bitmap)
1120 };
1121 entry = ctx->createAndLockTexture(&key, sampler, desc, NULL, 0);
1122
1123 } else {
1124 entry = sk_gr_create_bitmap_texture(ctx, &key, sampler, bitmap);
1125 }
1126 if (NULL == entry) {
1127 GrPrintf("---- failed to create texture for cache [%d %d]\n",
1128 bitmap.width(), bitmap.height());
1129 }
1130 }
1131
1132 if (NULL != entry) {
1133 newTexture = entry->texture();
reed@google.comac10a2d2010-12-22 21:39:39 +00001134 if (texture) {
1135 *texture = newTexture;
1136 }
1137 // IMPORTANT: We can't allow another SkGpuDevice to get this
1138 // cache entry until this one is destroyed!
1139 if (forDeviceRenderTarget) {
1140 ctx->detachCachedTexture(entry);
1141 }
1142 }
1143 return (TexCache*)entry;
1144}
1145
1146void SkGpuDevice::unlockCachedTexture(TexCache* cache) {
1147 this->context()->unlockTexture((GrTextureEntry*)cache);
1148}
1149
reed@google.com7b201d22011-01-11 18:59:23 +00001150///////////////////////////////////////////////////////////////////////////////
1151
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001152SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context,
1153 GrRenderTarget* rootRenderTarget)
1154 : fContext(context) {
1155
1156 GrAssert(NULL != context);
1157 GrAssert(NULL != rootRenderTarget);
1158
1159 // check this now rather than passing this value to SkGpuDevice cons.
1160 // we want the rt that is bound *now* in the 3D API, not the one
1161 // at the time of newDevice.
1162 if (SkGpuDevice::Current3DApiRenderTarget() == rootRenderTarget) {
1163 fRootRenderTarget = context->createRenderTargetFrom3DApiState();
1164 } else {
1165 fRootRenderTarget = rootRenderTarget;
1166 rootRenderTarget->ref();
1167 }
reed@google.com7b201d22011-01-11 18:59:23 +00001168 context->ref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001169
reed@google.com7b201d22011-01-11 18:59:23 +00001170}
1171
1172SkGpuDeviceFactory::~SkGpuDeviceFactory() {
1173 fContext->unref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001174 fRootRenderTarget->unref();
reed@google.com7b201d22011-01-11 18:59:23 +00001175}
1176
1177SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
1178 int width, int height,
1179 bool isOpaque, bool isLayer) {
1180 SkBitmap bm;
1181 bm.setConfig(config, width, height);
1182 bm.setIsOpaque(isOpaque);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001183 return new SkGpuDevice(fContext, bm, isLayer ? NULL : fRootRenderTarget);
reed@google.com7b201d22011-01-11 18:59:23 +00001184}
reed@google.comac10a2d2010-12-22 21:39:39 +00001185