blob: 114573aa2dbe3ed3c2b9955769c54a49ee9fd7af [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
bsalomon@google.com1da07462011-03-10 14:51:57 +00002 Copyright 2011 Google Inc.
reed@google.comac10a2d2010-12-22 21:39:39 +00003
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
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
Scroggo97c88c22011-05-11 14:05:25 +000025#include "SkColorFilter.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000026#include "SkDrawProcs.h"
27#include "SkGlyphCache.h"
reed@google.comc9aa5872011-04-05 21:05:37 +000028#include "SkUtils.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000029
30#define CACHE_LAYER_TEXTURES 1
31
32#if 0
33 extern bool (*gShouldDrawProc)();
34 #define CHECK_SHOULD_DRAW(draw) \
35 do { \
36 if (gShouldDrawProc && !gShouldDrawProc()) return; \
37 this->prepareRenderTarget(draw); \
38 } while (0)
39#else
40 #define CHECK_SHOULD_DRAW(draw) this->prepareRenderTarget(draw)
41#endif
42
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +000043// we use the same texture slot on GrPaint for bitmaps and shaders
44// (since drawBitmap, drawSprite, and drawDevice ignore skia's shader)
45enum {
46 kBitmapTextureIdx = 0,
47 kShaderTextureIdx = 0
48};
49
reed@google.comac10a2d2010-12-22 21:39:39 +000050///////////////////////////////////////////////////////////////////////////////
51
52SkGpuDevice::SkAutoCachedTexture::
53 SkAutoCachedTexture(SkGpuDevice* device,
54 const SkBitmap& bitmap,
55 const GrSamplerState& sampler,
56 GrTexture** texture) {
57 GrAssert(texture);
58 fTex = NULL;
59 *texture = this->set(device, bitmap, sampler);
60}
61
62SkGpuDevice::SkAutoCachedTexture::SkAutoCachedTexture() {
63 fTex = NULL;
64}
65
66GrTexture* SkGpuDevice::SkAutoCachedTexture::set(SkGpuDevice* device,
67 const SkBitmap& bitmap,
68 const GrSamplerState& sampler) {
69 if (fTex) {
70 fDevice->unlockCachedTexture(fTex);
71 }
72 fDevice = device;
73 GrTexture* texture = (GrTexture*)bitmap.getTexture();
74 if (texture) {
75 // return the native texture
76 fTex = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +000077 } else {
78 // look it up in our cache
79 fTex = device->lockCachedTexture(bitmap, sampler, &texture, false);
80 }
81 return texture;
82}
83
84SkGpuDevice::SkAutoCachedTexture::~SkAutoCachedTexture() {
85 if (fTex) {
86 fDevice->unlockCachedTexture(fTex);
87 }
88}
89
90///////////////////////////////////////////////////////////////////////////////
91
92bool gDoTraceDraw;
93
94struct GrSkDrawProcs : public SkDrawProcs {
95public:
96 GrContext* fContext;
97 GrTextContext* fTextContext;
98 GrFontScaler* fFontScaler; // cached in the skia glyphcache
99};
100
101///////////////////////////////////////////////////////////////////////////////
102
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000103GrRenderTarget* SkGpuDevice::Current3DApiRenderTarget() {
104 return (GrRenderTarget*) -1;
105}
106
107SkGpuDevice::SkGpuDevice(GrContext* context,
108 const SkBitmap& bitmap,
bsalomon@google.comb5b31682011-06-16 18:05:35 +0000109 GrRenderTarget* renderTargetOrNull,
110 bool isSaveLayer)
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000111 : SkDevice(NULL, bitmap, (NULL == renderTargetOrNull)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000112
113 fNeedPrepareRenderTarget = false;
114 fDrawProcs = NULL;
115
reed@google.com7b201d22011-01-11 18:59:23 +0000116 fContext = context;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000117 fContext->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000118
119 fCache = NULL;
120 fTexture = NULL;
121 fRenderTarget = NULL;
122 fNeedClear = false;
123
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000124 if (NULL == renderTargetOrNull) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000125 SkBitmap::Config c = bitmap.config();
126 if (c != SkBitmap::kRGB_565_Config) {
127 c = SkBitmap::kARGB_8888_Config;
128 }
129 SkBitmap bm;
130 bm.setConfig(c, this->width(), this->height());
131
132#if CACHE_LAYER_TEXTURES
133
134 fCache = this->lockCachedTexture(bm, GrSamplerState::ClampNoFilter(),
135 &fTexture, true);
136 if (fCache) {
137 SkASSERT(NULL != fTexture);
bsalomon@google.com1da07462011-03-10 14:51:57 +0000138 SkASSERT(NULL != fTexture->asRenderTarget());
reed@google.comac10a2d2010-12-22 21:39:39 +0000139 }
140#else
bsalomon@google.combb7f0762011-05-17 18:02:35 +0000141 const GrTextureDesc desc = {
142 kRenderTarget_GrTextureFlagBit,
143 kNone_GrAALevel,
reed@google.comac10a2d2010-12-22 21:39:39 +0000144 this->width(),
145 this->height(),
146 SkGr::Bitmap2PixelConfig(bm)
147 };
148
149 fTexture = fContext->createUncachedTexture(desc, NULL, 0);
150#endif
151 if (NULL != fTexture) {
152 fRenderTarget = fTexture->asRenderTarget();
153
154 GrAssert(NULL != fRenderTarget);
155
156 // we defer the actual clear until our gainFocus()
157 fNeedClear = true;
158
159 // wrap the bitmap with a pixelref to expose our texture
160 SkGrTexturePixelRef* pr = new SkGrTexturePixelRef(fTexture);
161 this->setPixelRef(pr, 0)->unref();
162 } else {
163 GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
164 this->width(), this->height());
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000165 GrAssert(false);
reed@google.comac10a2d2010-12-22 21:39:39 +0000166 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000167 } else {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000168 if (Current3DApiRenderTarget() == renderTargetOrNull) {
169 fRenderTarget = fContext->createRenderTargetFrom3DApiState();
170 } else {
171 fRenderTarget = renderTargetOrNull;
172 fRenderTarget->ref();
173 }
174 SkGrRenderTargetPixelRef* pr = new SkGrRenderTargetPixelRef(fRenderTarget);
175 this->setPixelRef(pr, 0)->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000176 }
177}
178
179SkGpuDevice::~SkGpuDevice() {
180 if (fDrawProcs) {
181 delete fDrawProcs;
182 }
183
184 if (fCache) {
185 GrAssert(NULL != fTexture);
186 GrAssert(fRenderTarget == fTexture->asRenderTarget());
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000187 fContext->unlockTexture((GrTextureEntry*)fCache);
reed@google.comac10a2d2010-12-22 21:39:39 +0000188 } else if (NULL != fTexture) {
189 GrAssert(!CACHE_LAYER_TEXTURES);
190 GrAssert(fRenderTarget == fTexture->asRenderTarget());
191 fTexture->unref();
192 } else if (NULL != fRenderTarget) {
193 fRenderTarget->unref();
194 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000195 fContext->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000196}
197
reed@google.comac10a2d2010-12-22 21:39:39 +0000198intptr_t SkGpuDevice::getLayerTextureHandle() const {
199 if (fTexture) {
200 return fTexture->getTextureHandle();
201 } else {
202 return 0;
203 }
204}
mike@reedtribe.orgea4ac972011-04-26 11:48:33 +0000205
206SkDeviceFactory* SkGpuDevice::onNewDeviceFactory() {
207 return SkNEW_ARGS(SkGpuDeviceFactory, (fContext, fRenderTarget));
208}
209
reed@google.comac10a2d2010-12-22 21:39:39 +0000210///////////////////////////////////////////////////////////////////////////////
211
212void SkGpuDevice::makeRenderTargetCurrent() {
213 fContext->setRenderTarget(fRenderTarget);
214 fContext->flush(true);
215 fNeedPrepareRenderTarget = true;
216}
217
218///////////////////////////////////////////////////////////////////////////////
219
220bool SkGpuDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
221 SkIRect bounds;
222 bounds.set(0, 0, this->width(), this->height());
223 if (!bounds.intersect(srcRect)) {
224 return false;
225 }
226
227 const int w = bounds.width();
228 const int h = bounds.height();
229 SkBitmap tmp;
230 // note we explicitly specify our rowBytes to be snug (no gap between rows)
231 tmp.setConfig(SkBitmap::kARGB_8888_Config, w, h, w * 4);
232 if (!tmp.allocPixels()) {
233 return false;
234 }
235
Scroggo813c33c2011-04-07 20:56:21 +0000236 tmp.lockPixels();
reed@google.comac10a2d2010-12-22 21:39:39 +0000237
Scroggoeb176032011-04-07 21:11:49 +0000238 bool read = fContext->readRenderTargetPixels(fRenderTarget,
239 bounds.fLeft, bounds.fTop,
240 bounds.width(), bounds.height(),
241 kRGBA_8888_GrPixelConfig,
242 tmp.getPixels());
Scroggo813c33c2011-04-07 20:56:21 +0000243 tmp.unlockPixels();
244 if (!read) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000245 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 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000257 GrPixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(),
258 bitmap.isOpaque());
reed@google.comac10a2d2010-12-22 21:39:39 +0000259 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,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000271 const SkClipStack& clipStack,
reed@google.com6f8f2922011-03-04 22:27:10 +0000272 const SkRegion& clipRegion,
273 const SkIPoint& origin) {
bsalomon@google.comcc4dac32011-05-10 13:52:42 +0000274 context->setMatrix(matrix);
reed@google.comac10a2d2010-12-22 21:39:39 +0000275
276 SkGrClipIterator iter;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000277 iter.reset(clipStack);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000278 const SkIRect& skBounds = clipRegion.getBounds();
279 GrRect bounds;
280 bounds.setLTRB(GrIntToScalar(skBounds.fLeft),
281 GrIntToScalar(skBounds.fTop),
282 GrIntToScalar(skBounds.fRight),
283 GrIntToScalar(skBounds.fBottom));
reed@google.com6f8f2922011-03-04 22:27:10 +0000284 GrClip grc(&iter, GrIntToScalar(-origin.x()), GrIntToScalar(-origin.y()),
285 &bounds);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000286 context->setClip(grc);
reed@google.comac10a2d2010-12-22 21:39:39 +0000287}
288
289// call this ever each draw call, to ensure that the context reflects our state,
290// and not the state from some other canvas/device
291void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) {
292 if (fNeedPrepareRenderTarget ||
bsalomon@google.com5782d712011-01-21 21:03:59 +0000293 fContext->getRenderTarget() != fRenderTarget) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000294
295 fContext->setRenderTarget(fRenderTarget);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000296 SkASSERT(draw.fClipStack);
297 convert_matrixclip(fContext, *draw.fMatrix,
reed@google.com6f8f2922011-03-04 22:27:10 +0000298 *draw.fClipStack, *draw.fClip, this->getOrigin());
reed@google.comac10a2d2010-12-22 21:39:39 +0000299 fNeedPrepareRenderTarget = false;
300 }
301}
302
reed@google.com46799cd2011-02-22 20:56:26 +0000303void SkGpuDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& clip,
304 const SkClipStack& clipStack) {
305 this->INHERITED::setMatrixClip(matrix, clip, clipStack);
bsalomon@google.coma7bf6e22011-04-11 19:20:46 +0000306 // We don't need to set them now because the context may not reflect this device.
307 fNeedPrepareRenderTarget = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000308}
309
310void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000311 const SkRegion& clip, const SkClipStack& clipStack) {
312
reed@google.comac10a2d2010-12-22 21:39:39 +0000313 fContext->setRenderTarget(fRenderTarget);
314
bsalomon@google.comd302f142011-03-03 13:54:13 +0000315 this->INHERITED::gainFocus(canvas, matrix, clip, clipStack);
reed@google.comac10a2d2010-12-22 21:39:39 +0000316
reed@google.com6f8f2922011-03-04 22:27:10 +0000317 convert_matrixclip(fContext, matrix, clipStack, clip, this->getOrigin());
reed@google.comac10a2d2010-12-22 21:39:39 +0000318
319 if (fNeedClear) {
bsalomon@google.com31a58402011-04-27 21:00:02 +0000320 fContext->clear(NULL, 0x0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000321 fNeedClear = false;
322 }
323}
324
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000325bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000326 if (NULL != fTexture) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000327 paint->setTexture(kBitmapTextureIdx, fTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +0000328 return true;
329 }
330 return false;
331}
332
333///////////////////////////////////////////////////////////////////////////////
334
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000335SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch);
336SK_COMPILE_ASSERT(SkShader::kDefault_BitmapType == 1, shader_type_mismatch);
337SK_COMPILE_ASSERT(SkShader::kRadial_BitmapType == 2, shader_type_mismatch);
338SK_COMPILE_ASSERT(SkShader::kSweep_BitmapType == 3, shader_type_mismatch);
339SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4,
340 shader_type_mismatch);
341SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 4, shader_type_mismatch);
reed@google.comac10a2d2010-12-22 21:39:39 +0000342
bsalomon@google.com5782d712011-01-21 21:03:59 +0000343static const GrSamplerState::SampleMode sk_bmp_type_to_sample_mode[] = {
344 (GrSamplerState::SampleMode) -1, // kNone_BitmapType
345 GrSamplerState::kNormal_SampleMode, // kDefault_BitmapType
346 GrSamplerState::kRadial_SampleMode, // kRadial_BitmapType
347 GrSamplerState::kSweep_SampleMode, // kSweep_BitmapType
348 GrSamplerState::kRadial2_SampleMode, // kTwoPointRadial_BitmapType
349};
350
351bool SkGpuDevice::skPaint2GrPaintNoShader(const SkPaint& skPaint,
352 bool justAlpha,
Scroggod757df22011-05-16 13:11:16 +0000353 GrPaint* grPaint,
354 bool constantColor) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000355
356 grPaint->fDither = skPaint.isDither();
357 grPaint->fAntiAlias = skPaint.isAntiAlias();
358
359 SkXfermode::Coeff sm = SkXfermode::kOne_Coeff;
360 SkXfermode::Coeff dm = SkXfermode::kISA_Coeff;
361
362 SkXfermode* mode = skPaint.getXfermode();
363 if (mode) {
364 if (!mode->asCoeff(&sm, &dm)) {
reed@google.com1a2e8d22011-01-21 22:08:29 +0000365 SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
bsalomon@google.com5782d712011-01-21 21:03:59 +0000366#if 0
367 return false;
368#endif
369 }
370 }
371 grPaint->fSrcBlendCoeff = sk_blend_to_grblend(sm);
372 grPaint->fDstBlendCoeff = sk_blend_to_grblend(dm);
373
374 if (justAlpha) {
375 uint8_t alpha = skPaint.getAlpha();
376 grPaint->fColor = GrColorPackRGBA(alpha, alpha, alpha, alpha);
Scroggod757df22011-05-16 13:11:16 +0000377 // justAlpha is currently set to true only if there is a texture,
378 // so constantColor should not also be true.
379 GrAssert(!constantColor);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000380 } else {
381 grPaint->fColor = SkGr::SkColor2GrColor(skPaint.getColor());
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000382 grPaint->setTexture(kShaderTextureIdx, NULL);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000383 }
Scroggo97c88c22011-05-11 14:05:25 +0000384 SkColorFilter* colorFilter = skPaint.getColorFilter();
385 SkColor color;
386 SkXfermode::Mode filterMode;
387 if (colorFilter != NULL && colorFilter->asColorMode(&color, &filterMode)) {
Scroggod757df22011-05-16 13:11:16 +0000388 if (!constantColor) {
389 grPaint->fColorFilterColor = SkGr::SkColor2GrColor(color);
390 grPaint->fColorFilterXfermode = filterMode;
391 return true;
392 }
393 SkColor filtered = colorFilter->filterColor(skPaint.getColor());
394 grPaint->fColor = SkGr::SkColor2GrColor(filtered);
Scroggo97c88c22011-05-11 14:05:25 +0000395 }
Scroggod757df22011-05-16 13:11:16 +0000396 grPaint->resetColorFilter();
bsalomon@google.com5782d712011-01-21 21:03:59 +0000397 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000398}
399
bsalomon@google.com5782d712011-01-21 21:03:59 +0000400bool SkGpuDevice::skPaint2GrPaintShader(const SkPaint& skPaint,
401 SkAutoCachedTexture* act,
402 const SkMatrix& ctm,
Scroggod757df22011-05-16 13:11:16 +0000403 GrPaint* grPaint,
404 bool constantColor) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000405
bsalomon@google.com5782d712011-01-21 21:03:59 +0000406 SkASSERT(NULL != act);
reed@google.comac10a2d2010-12-22 21:39:39 +0000407
bsalomon@google.com5782d712011-01-21 21:03:59 +0000408 SkShader* shader = skPaint.getShader();
reed@google.comac10a2d2010-12-22 21:39:39 +0000409 if (NULL == shader) {
Scroggod757df22011-05-16 13:11:16 +0000410 return this->skPaint2GrPaintNoShader(skPaint,
411 false,
412 grPaint,
413 constantColor);
414 } else if (!this->skPaint2GrPaintNoShader(skPaint, true, grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000415 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000416 }
417
bsalomon@google.com5782d712011-01-21 21:03:59 +0000418 SkPaint noAlphaPaint(skPaint);
419 noAlphaPaint.setAlpha(255);
420 shader->setContext(this->accessBitmap(false), noAlphaPaint, ctm);
reed@google.comac10a2d2010-12-22 21:39:39 +0000421
reed@google.comac10a2d2010-12-22 21:39:39 +0000422 SkBitmap bitmap;
423 SkMatrix matrix;
424 SkShader::TileMode tileModes[2];
425 SkScalar twoPointParams[3];
426 SkShader::BitmapType bmptype = shader->asABitmap(&bitmap, &matrix,
427 tileModes, twoPointParams);
428
bsalomon@google.com5782d712011-01-21 21:03:59 +0000429 GrSamplerState::SampleMode sampleMode = sk_bmp_type_to_sample_mode[bmptype];
430 if (-1 == sampleMode) {
431 SkDebugf("shader->asABitmap() == kNone_BitmapType\n");
432 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000433 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000434 GrSamplerState* sampler = grPaint->getTextureSampler(kShaderTextureIdx);
435 sampler->setSampleMode(sampleMode);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000436 if (skPaint.isFilterBitmap()) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000437 sampler->setFilter(GrSamplerState::kBilinear_Filter);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000438 } else {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000439 sampler->setFilter(GrSamplerState::kNearest_Filter);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000440 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000441 sampler->setWrapX(sk_tile_mode_to_grwrap(tileModes[0]));
442 sampler->setWrapY(sk_tile_mode_to_grwrap(tileModes[1]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000443 if (GrSamplerState::kRadial2_SampleMode == sampleMode) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000444 sampler->setRadial2Params(twoPointParams[0],
445 twoPointParams[1],
446 twoPointParams[2] < 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000447 }
448
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000449 GrTexture* texture = act->set(this, bitmap, *sampler);
reed@google.comac10a2d2010-12-22 21:39:39 +0000450 if (NULL == texture) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000451 SkDebugf("Couldn't convert bitmap to texture.\n");
452 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000453 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000454 grPaint->setTexture(kShaderTextureIdx, texture);
reed@google.comac10a2d2010-12-22 21:39:39 +0000455
456 // since our texture coords will be in local space, we wack the texture
457 // matrix to map them back into 0...1 before we load it
458 SkMatrix localM;
459 if (shader->getLocalMatrix(&localM)) {
460 SkMatrix inverse;
461 if (localM.invert(&inverse)) {
462 matrix.preConcat(inverse);
463 }
464 }
465 if (SkShader::kDefault_BitmapType == bmptype) {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000466 GrScalar sx = GrFixedToScalar(GR_Fixed1 / bitmap.width());
467 GrScalar sy = GrFixedToScalar(GR_Fixed1 / bitmap.height());
reed@google.comac10a2d2010-12-22 21:39:39 +0000468 matrix.postScale(sx, sy);
reed@google.comac10a2d2010-12-22 21:39:39 +0000469 } else if (SkShader::kRadial_BitmapType == bmptype) {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000470 GrScalar s = GrFixedToScalar(GR_Fixed1 / bitmap.width());
reed@google.comac10a2d2010-12-22 21:39:39 +0000471 matrix.postScale(s, s);
472 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000473 sampler->setMatrix(matrix);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000474
475 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000476}
477
478///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com5782d712011-01-21 21:03:59 +0000479
480class SkPositionSource {
481public:
482 SkPositionSource(const SkPoint* points, int count)
483 : fPoints(points), fCount(count) {}
484
485 int count() const { return fCount; }
486
487 void writeValue(int i, GrPoint* dstPosition) const {
488 SkASSERT(i < fCount);
489 dstPosition->fX = SkScalarToGrScalar(fPoints[i].fX);
490 dstPosition->fY = SkScalarToGrScalar(fPoints[i].fY);
491 }
492private:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000493 const SkPoint* fPoints;
bsalomon@google.com19628322011-02-03 21:30:17 +0000494 int fCount;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000495};
496
497class SkTexCoordSource {
498public:
499 SkTexCoordSource(const SkPoint* coords)
500 : fCoords(coords) {}
501
502 void writeValue(int i, GrPoint* dstCoord) const {
503 dstCoord->fX = SkScalarToGrScalar(fCoords[i].fX);
504 dstCoord->fY = SkScalarToGrScalar(fCoords[i].fY);
505 }
506private:
507 const SkPoint* fCoords;
508};
509
510class SkColorSource {
511public:
512 SkColorSource(const SkColor* colors) : fColors(colors) {}
513
514 void writeValue(int i, GrColor* dstColor) const {
515 *dstColor = SkGr::SkColor2GrColor(fColors[i]);
516 }
517private:
518 const SkColor* fColors;
519};
520
521class SkIndexSource {
522public:
523 SkIndexSource(const uint16_t* indices, int count)
524 : fIndices(indices), fCount(count) {
525 }
526
527 int count() const { return fCount; }
528
529 void writeValue(int i, uint16_t* dstIndex) const {
530 *dstIndex = fIndices[i];
531 }
532
533private:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000534 const uint16_t* fIndices;
bsalomon@google.com19628322011-02-03 21:30:17 +0000535 int fCount;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000536};
537
538///////////////////////////////////////////////////////////////////////////////
539
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000540#if 0 // not currently being used so don't compile,
541
bsalomon@google.com5782d712011-01-21 21:03:59 +0000542// can be used for positions or texture coordinates
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000543
bsalomon@google.com5782d712011-01-21 21:03:59 +0000544class SkRectFanSource {
545public:
546 SkRectFanSource(const SkRect& rect) : fRect(rect) {}
547
548 int count() const { return 4; }
549
550 void writeValue(int i, GrPoint* dstPoint) const {
551 SkASSERT(i < 4);
552 dstPoint->fX = SkScalarToGrScalar((i % 3) ? fRect.fRight :
553 fRect.fLeft);
554 dstPoint->fY = SkScalarToGrScalar((i < 2) ? fRect.fTop :
555 fRect.fBottom);
556 }
557private:
558 const SkRect& fRect;
559};
560
561class SkIRectFanSource {
562public:
563 SkIRectFanSource(const SkIRect& rect) : fRect(rect) {}
564
565 int count() const { return 4; }
566
567 void writeValue(int i, GrPoint* dstPoint) const {
568 SkASSERT(i < 4);
569 dstPoint->fX = (i % 3) ? GrIntToScalar(fRect.fRight) :
570 GrIntToScalar(fRect.fLeft);
571 dstPoint->fY = (i < 2) ? GrIntToScalar(fRect.fTop) :
572 GrIntToScalar(fRect.fBottom);
573 }
574private:
575 const SkIRect& fRect;
576};
577
578class SkMatRectFanSource {
579public:
580 SkMatRectFanSource(const SkRect& rect, const SkMatrix& matrix)
581 : fRect(rect), fMatrix(matrix) {}
582
583 int count() const { return 4; }
584
585 void writeValue(int i, GrPoint* dstPoint) const {
586 SkASSERT(i < 4);
587
588#if SK_SCALAR_IS_GR_SCALAR
589 fMatrix.mapXY((i % 3) ? fRect.fRight : fRect.fLeft,
590 (i < 2) ? fRect.fTop : fRect.fBottom,
591 (SkPoint*)dstPoint);
592#else
593 SkPoint dst;
594 fMatrix.mapXY((i % 3) ? fRect.fRight : fRect.fLeft,
595 (i < 2) ? fRect.fTop : fRect.fBottom,
596 &dst);
597 dstPoint->fX = SkScalarToGrScalar(dst.fX);
598 dstPoint->fY = SkScalarToGrScalar(dst.fY);
599#endif
600 }
601private:
602 const SkRect& fRect;
603 const SkMatrix& fMatrix;
604};
605
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000606#endif
607
reed@google.comac10a2d2010-12-22 21:39:39 +0000608///////////////////////////////////////////////////////////////////////////////
609
bsalomon@google.com398109c2011-04-14 18:40:27 +0000610void SkGpuDevice::clear(SkColor color) {
bsalomon@google.com31a58402011-04-27 21:00:02 +0000611 fContext->clear(NULL, color);
bsalomon@google.com398109c2011-04-14 18:40:27 +0000612}
613
reed@google.comac10a2d2010-12-22 21:39:39 +0000614void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
615 CHECK_SHOULD_DRAW(draw);
616
bsalomon@google.com5782d712011-01-21 21:03:59 +0000617 GrPaint grPaint;
618 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +0000619 if (!this->skPaint2GrPaintShader(paint,
620 &act,
621 *draw.fMatrix,
622 &grPaint,
623 true)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000624 return;
625 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000626
627 fContext->drawPaint(grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000628}
629
630// must be in SkCanvas::PointMode order
bsalomon@google.comffca4002011-02-22 20:34:01 +0000631static const GrPrimitiveType gPointMode2PrimtiveType[] = {
632 kPoints_PrimitiveType,
633 kLines_PrimitiveType,
634 kLineStrip_PrimitiveType
reed@google.comac10a2d2010-12-22 21:39:39 +0000635};
636
637void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000638 size_t count, const SkPoint pts[], const SkPaint& paint) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000639 CHECK_SHOULD_DRAW(draw);
640
641 SkScalar width = paint.getStrokeWidth();
642 if (width < 0) {
643 return;
644 }
645
646 // we only handle hairlines here, else we let the SkDraw call our drawPath()
647 if (width > 0) {
648 draw.drawPoints(mode, count, pts, paint, true);
649 return;
650 }
651
bsalomon@google.com5782d712011-01-21 21:03:59 +0000652 GrPaint grPaint;
653 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +0000654 if (!this->skPaint2GrPaintShader(paint,
655 &act,
656 *draw.fMatrix,
657 &grPaint,
658 true)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000659 return;
660 }
661
reed@google.comac10a2d2010-12-22 21:39:39 +0000662#if SK_SCALAR_IS_GR_SCALAR
bsalomon@google.com5782d712011-01-21 21:03:59 +0000663 fContext->drawVertices(grPaint,
664 gPointMode2PrimtiveType[mode],
665 count,
666 (GrPoint*)pts,
667 NULL,
668 NULL,
669 NULL,
670 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000671#else
bsalomon@google.com5782d712011-01-21 21:03:59 +0000672 fContext->drawCustomVertices(grPaint,
673 gPointMode2PrimtiveType[mode],
674 SkPositionSource(pts, count));
reed@google.comac10a2d2010-12-22 21:39:39 +0000675#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000676}
677
reed@google.comc9aa5872011-04-05 21:05:37 +0000678///////////////////////////////////////////////////////////////////////////////
679
reed@google.comac10a2d2010-12-22 21:39:39 +0000680void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
681 const SkPaint& paint) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000682 CHECK_SHOULD_DRAW(draw);
683
684 bool doStroke = paint.getStyle() == SkPaint::kStroke_Style;
685 SkScalar width = paint.getStrokeWidth();
686
687 /*
688 We have special code for hairline strokes, miter-strokes, and fills.
689 Anything else we just call our path code.
690 */
691 bool usePath = doStroke && width > 0 &&
692 paint.getStrokeJoin() != SkPaint::kMiter_Join;
693 // another reason we might need to call drawPath...
694 if (paint.getMaskFilter()) {
695 usePath = true;
696 }
reed@google.com67db6642011-05-26 11:46:35 +0000697 // until we aa rotated rects...
698 if (!usePath && paint.isAntiAlias() && !draw.fMatrix->rectStaysRect()) {
699 usePath = true;
700 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000701
702 if (usePath) {
703 SkPath path;
704 path.addRect(rect);
705 this->drawPath(draw, path, paint, NULL, true);
706 return;
707 }
708
709 GrPaint grPaint;
710 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +0000711 if (!this->skPaint2GrPaintShader(paint,
712 &act,
713 *draw.fMatrix,
714 &grPaint,
715 true)) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000716 return;
717 }
reed@google.com20efde72011-05-09 17:00:02 +0000718 fContext->drawRect(grPaint, rect, doStroke ? width : -1);
reed@google.comac10a2d2010-12-22 21:39:39 +0000719}
720
reed@google.com69302852011-02-16 18:08:07 +0000721#include "SkMaskFilter.h"
722#include "SkBounder.h"
723
reed@google.com69302852011-02-16 18:08:07 +0000724static bool drawWithMaskFilter(GrContext* context, const SkPath& path,
725 SkMaskFilter* filter, const SkMatrix& matrix,
726 const SkRegion& clip, SkBounder* bounder,
727 GrPaint* grp) {
728 SkMask srcM, dstM;
729
730 if (!SkDraw::DrawToMask(path, &clip.getBounds(), filter, &matrix, &srcM,
731 SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
732 return false;
733 }
734
735 SkAutoMaskImage autoSrc(&srcM, false);
736
737 if (!filter->filterMask(&dstM, srcM, matrix, NULL)) {
738 return false;
739 }
740 // this will free-up dstM when we're done (allocated in filterMask())
741 SkAutoMaskImage autoDst(&dstM, false);
742
743 if (clip.quickReject(dstM.fBounds)) {
744 return false;
745 }
746 if (bounder && !bounder->doIRect(dstM.fBounds)) {
747 return false;
748 }
749
750 // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
751 // the current clip (and identity matrix) and grpaint settings
752
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000753 // used to compute inverse view, if necessary
754 GrMatrix ivm = context->getMatrix();
755
reed@google.com0c219b62011-02-16 21:31:18 +0000756 GrAutoMatrix avm(context, GrMatrix::I());
reed@google.com69302852011-02-16 18:08:07 +0000757
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000758 const GrTextureDesc desc = {
759 kNone_GrTextureFlags,
760 kNone_GrAALevel,
reed@google.com69302852011-02-16 18:08:07 +0000761 dstM.fBounds.width(),
762 dstM.fBounds.height(),
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000763 kAlpha_8_GrPixelConfig
reed@google.com69302852011-02-16 18:08:07 +0000764 };
765
766 GrTexture* texture = context->createUncachedTexture(desc, dstM.fImage,
767 dstM.fRowBytes);
768 if (NULL == texture) {
769 return false;
770 }
771
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000772 if (grp->hasTextureOrMask() && ivm.invert(&ivm)) {
773 grp->preConcatActiveSamplerMatrices(ivm);
774 }
775
776 static const int MASK_IDX = GrPaint::kMaxMasks - 1;
777 // we assume the last mask index is available for use
778 GrAssert(NULL == grp->getMask(MASK_IDX));
779 grp->setMask(MASK_IDX, texture);
reed@google.com0c219b62011-02-16 21:31:18 +0000780 texture->unref();
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000781 grp->getMaskSampler(MASK_IDX)->setClampNoFilter();
reed@google.com69302852011-02-16 18:08:07 +0000782
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000783 GrRect d;
784 d.setLTRB(GrIntToScalar(dstM.fBounds.fLeft),
reed@google.com0c219b62011-02-16 21:31:18 +0000785 GrIntToScalar(dstM.fBounds.fTop),
786 GrIntToScalar(dstM.fBounds.fRight),
787 GrIntToScalar(dstM.fBounds.fBottom));
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000788
789 GrMatrix m;
790 m.setTranslate(-dstM.fBounds.fLeft, -dstM.fBounds.fTop);
791 m.postIDiv(dstM.fBounds.width(), dstM.fBounds.height());
792 grp->getMaskSampler(MASK_IDX)->setMatrix(m);
793
794 context->drawRect(*grp, d);
reed@google.com69302852011-02-16 18:08:07 +0000795 return true;
796}
reed@google.com69302852011-02-16 18:08:07 +0000797
reed@google.com0c219b62011-02-16 21:31:18 +0000798void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
reed@google.comac10a2d2010-12-22 21:39:39 +0000799 const SkPaint& paint, const SkMatrix* prePathMatrix,
800 bool pathIsMutable) {
801 CHECK_SHOULD_DRAW(draw);
802
bsalomon@google.com5782d712011-01-21 21:03:59 +0000803 GrPaint grPaint;
804 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +0000805 if (!this->skPaint2GrPaintShader(paint,
806 &act,
807 *draw.fMatrix,
808 &grPaint,
809 true)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000810 return;
811 }
812
reed@google.com0c219b62011-02-16 21:31:18 +0000813 // BEGIN lift from SkDraw::drawPath()
814
815 SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
816 bool doFill = true;
817 SkPath tmpPath;
reed@google.comac10a2d2010-12-22 21:39:39 +0000818
819 if (prePathMatrix) {
reed@google.come3445642011-02-16 23:20:39 +0000820 SkPath* result = pathPtr;
reed@google.com0c219b62011-02-16 21:31:18 +0000821
reed@google.come3445642011-02-16 23:20:39 +0000822 if (!pathIsMutable) {
823 result = &tmpPath;
824 pathIsMutable = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000825 }
reed@google.come3445642011-02-16 23:20:39 +0000826 // should I push prePathMatrix on our MV stack temporarily, instead
827 // of applying it here? See SkDraw.cpp
828 pathPtr->transform(*prePathMatrix, result);
829 pathPtr = result;
reed@google.comac10a2d2010-12-22 21:39:39 +0000830 }
reed@google.com0c219b62011-02-16 21:31:18 +0000831 // at this point we're done with prePathMatrix
832 SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
reed@google.comac10a2d2010-12-22 21:39:39 +0000833
bsalomon@google.com04de7822011-03-25 18:04:43 +0000834 // This "if" is not part of the SkDraw::drawPath() lift.
835 // When we get a 1.0 wide stroke we hairline stroke it instead of creating
836 // a new stroked-path. This is motivated by canvas2D sites that draw
837 // lines as 1.0 wide stroked paths. We can consider doing an alpha-modulated-
838 // hairline for width < 1.0 when AA is enabled.
839 static const int gMatrixMask = ~(SkMatrix::kIdentity_Mask |
840 SkMatrix::kTranslate_Mask);
841 if (!paint.getPathEffect() &&
842 SkPaint::kStroke_Style == paint.getStyle() &&
843 !(draw.fMatrix->getType() & gMatrixMask) &&
844 SK_Scalar1 == paint.getStrokeWidth()) {
845 doFill = false;
846 }
847
848 if (doFill && (paint.getPathEffect() ||
849 paint.getStyle() != SkPaint::kFill_Style)) {
reed@google.com0c219b62011-02-16 21:31:18 +0000850 doFill = paint.getFillPath(*pathPtr, &tmpPath);
851 pathPtr = &tmpPath;
852 }
853
854 // END lift from SkDraw::drawPath()
855
reed@google.com69302852011-02-16 18:08:07 +0000856 if (paint.getMaskFilter()) {
reed@google.com0c219b62011-02-16 21:31:18 +0000857 // avoid possibly allocating a new path in transform if we can
858 SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
859
860 // transform the path into device space
reed@google.come3445642011-02-16 23:20:39 +0000861 pathPtr->transform(*draw.fMatrix, devPathPtr);
reed@google.com0c219b62011-02-16 21:31:18 +0000862
863 drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
reed@google.com69302852011-02-16 18:08:07 +0000864 *draw.fMatrix, *draw.fClip, draw.fBounder, &grPaint);
865 return;
866 }
reed@google.com69302852011-02-16 18:08:07 +0000867
bsalomon@google.comffca4002011-02-22 20:34:01 +0000868 GrPathFill fill = kHairLine_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000869
reed@google.com0c219b62011-02-16 21:31:18 +0000870 if (doFill) {
871 switch (pathPtr->getFillType()) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000872 case SkPath::kWinding_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000873 fill = kWinding_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000874 break;
875 case SkPath::kEvenOdd_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000876 fill = kEvenOdd_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000877 break;
878 case SkPath::kInverseWinding_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000879 fill = kInverseWinding_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000880 break;
881 case SkPath::kInverseEvenOdd_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000882 fill = kInverseEvenOdd_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000883 break;
884 default:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000885 SkDebugf("Unsupported path fill type\n");
reed@google.comac10a2d2010-12-22 21:39:39 +0000886 return;
887 }
888 }
889
reed@google.com07f3ee12011-05-16 17:21:57 +0000890 fContext->drawPath(grPaint, *pathPtr, fill);
reed@google.comac10a2d2010-12-22 21:39:39 +0000891}
892
reed@google.comac10a2d2010-12-22 21:39:39 +0000893void SkGpuDevice::drawBitmap(const SkDraw& draw,
894 const SkBitmap& bitmap,
895 const SkIRect* srcRectPtr,
896 const SkMatrix& m,
897 const SkPaint& paint) {
898 CHECK_SHOULD_DRAW(draw);
899
900 SkIRect srcRect;
901 if (NULL == srcRectPtr) {
902 srcRect.set(0, 0, bitmap.width(), bitmap.height());
903 } else {
904 srcRect = *srcRectPtr;
905 }
906
bsalomon@google.com5782d712011-01-21 21:03:59 +0000907 GrPaint grPaint;
Scroggod757df22011-05-16 13:11:16 +0000908 if (!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000909 return;
910 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000911 GrSamplerState* sampler = grPaint.getTextureSampler(kBitmapTextureIdx);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000912 if (paint.isFilterBitmap()) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000913 sampler->setFilter(GrSamplerState::kBilinear_Filter);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000914 } else {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000915 sampler->setFilter(GrSamplerState::kNearest_Filter);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000916 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000917
bsalomon@google.com91958362011-06-13 17:58:13 +0000918 const int maxTextureSize = fContext->getMaxTextureSize();
919 if (bitmap.getTexture() || (bitmap.width() <= maxTextureSize &&
920 bitmap.height() <= maxTextureSize)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000921 // take the fast case
bsalomon@google.com5782d712011-01-21 21:03:59 +0000922 this->internalDrawBitmap(draw, bitmap, srcRect, m, &grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000923 return;
924 }
925
926 // undo the translate done by SkCanvas
927 int DX = SkMax32(0, srcRect.fLeft);
928 int DY = SkMax32(0, srcRect.fTop);
929 // compute clip bounds in local coordinates
930 SkIRect clipRect;
931 {
932 SkRect r;
933 r.set(draw.fClip->getBounds());
934 SkMatrix matrix, inverse;
935 matrix.setConcat(*draw.fMatrix, m);
936 if (!matrix.invert(&inverse)) {
937 return;
938 }
939 inverse.mapRect(&r);
940 r.roundOut(&clipRect);
941 // apply the canvas' translate to our local clip
942 clipRect.offset(DX, DY);
943 }
944
bsalomon@google.com91958362011-06-13 17:58:13 +0000945 int nx = bitmap.width() / maxTextureSize;
946 int ny = bitmap.height() / maxTextureSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000947 for (int x = 0; x <= nx; x++) {
948 for (int y = 0; y <= ny; y++) {
949 SkIRect tileR;
bsalomon@google.com91958362011-06-13 17:58:13 +0000950 tileR.set(x * maxTextureSize, y * maxTextureSize,
951 (x + 1) * maxTextureSize, (y + 1) * maxTextureSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000952 if (!SkIRect::Intersects(tileR, clipRect)) {
953 continue;
954 }
955
956 SkIRect srcR = tileR;
957 if (!srcR.intersect(srcRect)) {
958 continue;
959 }
960
961 SkBitmap tmpB;
962 if (bitmap.extractSubset(&tmpB, tileR)) {
963 // now offset it to make it "local" to our tmp bitmap
964 srcR.offset(-tileR.fLeft, -tileR.fTop);
965
966 SkMatrix tmpM(m);
967 {
968 int dx = tileR.fLeft - DX + SkMax32(0, srcR.fLeft);
969 int dy = tileR.fTop - DY + SkMax32(0, srcR.fTop);
970 tmpM.preTranslate(SkIntToScalar(dx), SkIntToScalar(dy));
971 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000972 this->internalDrawBitmap(draw, tmpB, srcR, tmpM, &grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000973 }
974 }
975 }
976}
977
978/*
979 * This is called by drawBitmap(), which has to handle images that may be too
980 * large to be represented by a single texture.
981 *
bsalomon@google.com5782d712011-01-21 21:03:59 +0000982 * internalDrawBitmap assumes that the specified bitmap will fit in a texture
983 * and that non-texture portion of the GrPaint has already been setup.
reed@google.comac10a2d2010-12-22 21:39:39 +0000984 */
985void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
986 const SkBitmap& bitmap,
987 const SkIRect& srcRect,
988 const SkMatrix& m,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000989 GrPaint* grPaint) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000990 SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() &&
991 bitmap.height() <= fContext->getMaxTextureSize());
reed@google.comac10a2d2010-12-22 21:39:39 +0000992
993 SkAutoLockPixels alp(bitmap);
994 if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
995 return;
996 }
997
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000998 GrSamplerState* sampler = grPaint->getTextureSampler(kBitmapTextureIdx);
999
1000 sampler->setWrapX(GrSamplerState::kClamp_WrapMode);
1001 sampler->setWrapY(GrSamplerState::kClamp_WrapMode);
1002 sampler->setSampleMode(GrSamplerState::kNormal_SampleMode);
1003 sampler->setMatrix(GrMatrix::I());
reed@google.comac10a2d2010-12-22 21:39:39 +00001004
1005 GrTexture* texture;
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001006 SkAutoCachedTexture act(this, bitmap, *sampler, &texture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001007 if (NULL == texture) {
1008 return;
1009 }
1010
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001011 grPaint->setTexture(kShaderTextureIdx, texture);
reed@google.com46799cd2011-02-22 20:56:26 +00001012
reed@google.com20efde72011-05-09 17:00:02 +00001013 GrRect dstRect = SkRect::MakeWH(GrIntToScalar(srcRect.width()),
1014 GrIntToScalar(srcRect.height()));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001015 GrRect paintRect;
junov@google.com6acc9b32011-05-16 18:32:07 +00001016 paintRect.setLTRB(GrFixedToScalar((srcRect.fLeft << 16) / bitmap.width()),
1017 GrFixedToScalar((srcRect.fTop << 16) / bitmap.height()),
1018 GrFixedToScalar((srcRect.fRight << 16) / bitmap.width()),
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001019 GrFixedToScalar((srcRect.fBottom << 16) / bitmap.height()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001020
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001021 if (GrSamplerState::kNearest_Filter != sampler->getFilter() &&
junov@google.com6acc9b32011-05-16 18:32:07 +00001022 (srcRect.width() < bitmap.width() ||
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001023 srcRect.height() < bitmap.height())) {
junov@google.com6acc9b32011-05-16 18:32:07 +00001024 // If drawing a subrect of the bitmap and filtering is enabled,
1025 // use a constrained texture domain to avoid color bleeding
1026 GrScalar left, top, right, bottom;
1027 if (srcRect.width() > 1) {
1028 GrScalar border = GR_ScalarHalf / bitmap.width();
1029 left = paintRect.left() + border;
1030 right = paintRect.right() - border;
1031 } else {
1032 left = right = GrScalarHalf(paintRect.left() + paintRect.right());
1033 }
1034 if (srcRect.height() > 1) {
1035 GrScalar border = GR_ScalarHalf / bitmap.height();
1036 top = paintRect.top() + border;
1037 bottom = paintRect.bottom() - border;
1038 } else {
1039 top = bottom = GrScalarHalf(paintRect.top() + paintRect.bottom());
1040 }
1041 GrRect textureDomain;
1042 textureDomain.setLTRB(left, top, right, bottom);
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001043 sampler->setTextureDomain(textureDomain);
junov@google.com6acc9b32011-05-16 18:32:07 +00001044 }
1045
bsalomon@google.comcc4dac32011-05-10 13:52:42 +00001046 fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m);
reed@google.comac10a2d2010-12-22 21:39:39 +00001047}
1048
1049void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
1050 int left, int top, const SkPaint& paint) {
1051 CHECK_SHOULD_DRAW(draw);
1052
1053 SkAutoLockPixels alp(bitmap);
1054 if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
1055 return;
1056 }
1057
bsalomon@google.com5782d712011-01-21 21:03:59 +00001058 GrPaint grPaint;
Scroggod757df22011-05-16 13:11:16 +00001059 if(!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001060 return;
1061 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001062
bsalomon@google.com5782d712011-01-21 21:03:59 +00001063 GrAutoMatrix avm(fContext, GrMatrix::I());
1064
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001065 GrSamplerState* sampler = grPaint.getTextureSampler(kBitmapTextureIdx);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001066
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001067 GrTexture* texture;
1068 sampler->setClampNoFilter();
1069 SkAutoCachedTexture act(this, bitmap, *sampler, &texture);
1070
1071 grPaint.setTexture(kBitmapTextureIdx, texture);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001072
bsalomon@google.com5782d712011-01-21 21:03:59 +00001073 fContext->drawRectToRect(grPaint,
reed@google.com20efde72011-05-09 17:00:02 +00001074 GrRect::MakeXYWH(GrIntToScalar(left),
1075 GrIntToScalar(top),
1076 GrIntToScalar(bitmap.width()),
1077 GrIntToScalar(bitmap.height())),
1078 GrRect::MakeWH(GR_Scalar1, GR_Scalar1));
reed@google.comac10a2d2010-12-22 21:39:39 +00001079}
1080
1081void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* dev,
1082 int x, int y, const SkPaint& paint) {
1083 CHECK_SHOULD_DRAW(draw);
1084
bsalomon@google.com5782d712011-01-21 21:03:59 +00001085 GrPaint grPaint;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001086 if (!((SkGpuDevice*)dev)->bindDeviceAsTexture(&grPaint) ||
Scroggod757df22011-05-16 13:11:16 +00001087 !this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001088 return;
reed@google.comac10a2d2010-12-22 21:39:39 +00001089 }
bsalomon@google.com5782d712011-01-21 21:03:59 +00001090
bsalomon@google.comb5b31682011-06-16 18:05:35 +00001091 GrTexture* devTex = grPaint.getTexture(0);
1092 SkASSERT(NULL != devTex);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001093
1094 const SkBitmap& bm = dev->accessBitmap(false);
1095 int w = bm.width();
1096 int h = bm.height();
1097
1098 GrAutoMatrix avm(fContext, GrMatrix::I());
1099
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001100 grPaint.getTextureSampler(kBitmapTextureIdx)->setClampNoFilter();
bsalomon@google.com5782d712011-01-21 21:03:59 +00001101
bsalomon@google.comb5b31682011-06-16 18:05:35 +00001102 GrRect dstRect = GrRect::MakeXYWH(GrIntToScalar(x),
1103 GrIntToScalar(y),
1104 GrIntToScalar(w),
1105 GrIntToScalar(h));
1106 // The device being drawn may not fill up its texture (saveLayer uses
1107 // the approximate ).
1108 GrRect srcRect = GrRect::MakeWH(GR_Scalar1 * w / devTex->width(),
1109 GR_Scalar1 * h / devTex->height());
1110
1111 fContext->drawRectToRect(grPaint, dstRect, srcRect);
reed@google.comac10a2d2010-12-22 21:39:39 +00001112}
1113
1114///////////////////////////////////////////////////////////////////////////////
1115
1116// must be in SkCanvas::VertexMode order
bsalomon@google.comffca4002011-02-22 20:34:01 +00001117static const GrPrimitiveType gVertexMode2PrimitiveType[] = {
1118 kTriangles_PrimitiveType,
1119 kTriangleStrip_PrimitiveType,
1120 kTriangleFan_PrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +00001121};
1122
1123void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
1124 int vertexCount, const SkPoint vertices[],
1125 const SkPoint texs[], const SkColor colors[],
1126 SkXfermode* xmode,
1127 const uint16_t indices[], int indexCount,
1128 const SkPaint& paint) {
1129 CHECK_SHOULD_DRAW(draw);
1130
bsalomon@google.com5782d712011-01-21 21:03:59 +00001131 GrPaint grPaint;
1132 SkAutoCachedTexture act;
1133 // we ignore the shader if texs is null.
1134 if (NULL == texs) {
Scroggod757df22011-05-16 13:11:16 +00001135 if (!this->skPaint2GrPaintNoShader(paint,
1136 false,
1137 &grPaint,
1138 NULL == colors)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001139 return;
1140 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001141 } else {
reed@google.com1a2e8d22011-01-21 22:08:29 +00001142 if (!this->skPaint2GrPaintShader(paint, &act,
1143 *draw.fMatrix,
Scroggod757df22011-05-16 13:11:16 +00001144 &grPaint,
1145 NULL == colors)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001146 return;
1147 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001148 }
bsalomon@google.com5782d712011-01-21 21:03:59 +00001149
1150 if (NULL != xmode && NULL != texs && NULL != colors) {
1151 SkXfermode::Mode mode;
1152 if (!SkXfermode::IsMode(xmode, &mode) ||
1153 SkXfermode::kMultiply_Mode != mode) {
1154 SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
1155#if 0
1156 return
1157#endif
1158 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001159 }
bsalomon@google.com5782d712011-01-21 21:03:59 +00001160
1161#if SK_SCALAR_IS_GR_SCALAR
1162 // even if GrColor and SkColor byte offsets match we need
1163 // to perform pre-multiply.
1164 if (NULL == colors) {
1165 fContext->drawVertices(grPaint,
1166 gVertexMode2PrimitiveType[vmode],
1167 vertexCount,
1168 (GrPoint*) vertices,
1169 (GrPoint*) texs,
1170 NULL,
1171 indices,
1172 indexCount);
1173 } else
1174#endif
1175 {
1176 SkTexCoordSource texSrc(texs);
1177 SkColorSource colSrc(colors);
1178 SkIndexSource idxSrc(indices, indexCount);
1179
1180 fContext->drawCustomVertices(grPaint,
1181 gVertexMode2PrimitiveType[vmode],
1182 SkPositionSource(vertices, vertexCount),
1183 (NULL == texs) ? NULL : &texSrc,
1184 (NULL == colors) ? NULL : &colSrc,
1185 (NULL == indices) ? NULL : &idxSrc);
reed@google.comac10a2d2010-12-22 21:39:39 +00001186 }
1187}
1188
1189///////////////////////////////////////////////////////////////////////////////
1190
1191static void GlyphCacheAuxProc(void* data) {
1192 delete (GrFontScaler*)data;
1193}
1194
1195static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
1196 void* auxData;
1197 GrFontScaler* scaler = NULL;
1198 if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
1199 scaler = (GrFontScaler*)auxData;
1200 }
1201 if (NULL == scaler) {
1202 scaler = new SkGrFontScaler(cache);
1203 cache->setAuxProc(GlyphCacheAuxProc, scaler);
1204 }
1205 return scaler;
1206}
1207
1208static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
1209 SkFixed fx, SkFixed fy,
1210 const SkGlyph& glyph) {
1211 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1212
1213 GrSkDrawProcs* procs = (GrSkDrawProcs*)state.fDraw->fProcs;
1214
1215 if (NULL == procs->fFontScaler) {
1216 procs->fFontScaler = get_gr_font_scaler(state.fCache);
1217 }
reed@google.com39ce0ac2011-04-08 15:42:19 +00001218
1219 /*
reed@google.com3b139f52011-06-07 17:56:25 +00001220 * What should we do with fy? (assuming horizontal/latin text)
reed@google.com39ce0ac2011-04-08 15:42:19 +00001221 *
reed@google.com3b139f52011-06-07 17:56:25 +00001222 * The raster code calls SkFixedFloorToFixed on it, as it does with fx.
1223 * It calls that rather than round, because our caller has already added
1224 * SK_FixedHalf, so that calling floor gives us the rounded integer.
1225 *
1226 * Test code between raster and gpu (they should draw the same)
1227 *
1228 * canvas->drawText("Hamburgefons", 12, 0, 16.5f, paint);
1229 *
1230 * Perhaps we should only perform this integralization if there is no
1231 * fExtMatrix...
reed@google.com39ce0ac2011-04-08 15:42:19 +00001232 */
reed@google.com3b139f52011-06-07 17:56:25 +00001233 fy = SkFixedFloorToFixed(fy);
1234
reed@google.comac10a2d2010-12-22 21:39:39 +00001235 procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), fx, 0),
reed@google.com3b139f52011-06-07 17:56:25 +00001236 SkFixedFloorToFixed(fx), fy,
reed@google.comac10a2d2010-12-22 21:39:39 +00001237 procs->fFontScaler);
1238}
1239
bsalomon@google.com5782d712011-01-21 21:03:59 +00001240SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001241
1242 // deferred allocation
1243 if (NULL == fDrawProcs) {
1244 fDrawProcs = new GrSkDrawProcs;
1245 fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
1246 fDrawProcs->fContext = fContext;
1247 }
1248
1249 // init our (and GL's) state
1250 fDrawProcs->fTextContext = context;
1251 fDrawProcs->fFontScaler = NULL;
1252 return fDrawProcs;
1253}
1254
1255void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
1256 size_t byteLength, SkScalar x, SkScalar y,
1257 const SkPaint& paint) {
1258 CHECK_SHOULD_DRAW(draw);
1259
1260 if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1261 // this guy will just call our drawPath()
1262 draw.drawText((const char*)text, byteLength, x, y, paint);
1263 } else {
reed@google.comac10a2d2010-12-22 21:39:39 +00001264 SkDraw myDraw(draw);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001265
1266 GrPaint grPaint;
1267 SkAutoCachedTexture act;
1268
Scroggod757df22011-05-16 13:11:16 +00001269 if (!this->skPaint2GrPaintShader(paint,
1270 &act,
1271 *draw.fMatrix,
1272 &grPaint,
1273 true)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001274 return;
1275 }
bsalomon@google.comcc4dac32011-05-10 13:52:42 +00001276 GrTextContext context(fContext, grPaint, draw.fExtMatrix);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001277 myDraw.fProcs = this->initDrawForText(&context);
reed@google.comac10a2d2010-12-22 21:39:39 +00001278 this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
1279 }
1280}
1281
1282void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
1283 size_t byteLength, const SkScalar pos[],
1284 SkScalar constY, int scalarsPerPos,
1285 const SkPaint& paint) {
1286 CHECK_SHOULD_DRAW(draw);
1287
1288 if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1289 // this guy will just call our drawPath()
1290 draw.drawPosText((const char*)text, byteLength, pos, constY,
1291 scalarsPerPos, paint);
1292 } else {
reed@google.comac10a2d2010-12-22 21:39:39 +00001293 SkDraw myDraw(draw);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001294
1295 GrPaint grPaint;
1296 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +00001297 if (!this->skPaint2GrPaintShader(paint,
1298 &act,
1299 *draw.fMatrix,
1300 &grPaint,
1301 true)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001302 return;
1303 }
1304
bsalomon@google.comcc4dac32011-05-10 13:52:42 +00001305 GrTextContext context(fContext, grPaint, draw.fExtMatrix);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001306 myDraw.fProcs = this->initDrawForText(&context);
reed@google.comac10a2d2010-12-22 21:39:39 +00001307 this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
1308 scalarsPerPos, paint);
1309 }
1310}
1311
1312void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
1313 size_t len, const SkPath& path,
1314 const SkMatrix* m, const SkPaint& paint) {
1315 CHECK_SHOULD_DRAW(draw);
1316
1317 SkASSERT(draw.fDevice == this);
1318 draw.drawTextOnPath((const char*)text, len, path, m, paint);
1319}
1320
1321///////////////////////////////////////////////////////////////////////////////
1322
reed@google.comf67e4cf2011-03-15 20:56:58 +00001323bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
1324 if (!paint.isLCDRenderText()) {
1325 // we're cool with the paint as is
1326 return false;
1327 }
1328
1329 if (paint.getShader() ||
1330 paint.getXfermode() || // unless its srcover
1331 paint.getMaskFilter() ||
1332 paint.getRasterizer() ||
1333 paint.getColorFilter() ||
1334 paint.getPathEffect() ||
1335 paint.isFakeBoldText() ||
1336 paint.getStyle() != SkPaint::kFill_Style) {
1337 // turn off lcd
1338 flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
1339 flags->fHinting = paint.getHinting();
1340 return true;
1341 }
1342 // we're cool with the paint as is
1343 return false;
1344}
1345
1346///////////////////////////////////////////////////////////////////////////////
1347
reed@google.comac10a2d2010-12-22 21:39:39 +00001348SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001349 const GrSamplerState& sampler,
1350 GrTexture** texture,
bsalomon@google.comb5b31682011-06-16 18:05:35 +00001351 bool forDeviceRenderTarget,
1352 bool isSaveLayer) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001353 GrTexture* newTexture = NULL;
1354 GrTextureEntry* entry = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001355 GrContext* ctx = this->context();
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001356
reed@google.comac10a2d2010-12-22 21:39:39 +00001357 if (forDeviceRenderTarget) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001358 const GrTextureDesc desc = {
1359 kRenderTarget_GrTextureFlagBit,
1360 kNone_GrAALevel,
1361 bitmap.width(),
1362 bitmap.height(),
1363 SkGr::Bitmap2PixelConfig(bitmap)
1364 };
bsalomon@google.comb5b31682011-06-16 18:05:35 +00001365 if (isSaveLayer) {
1366 // we know layers will only be drawn through drawDevice.
1367 // drawDevice has been made to work with content embedded in a
1368 // larger texture so its okay to use the approximate version.
1369 entry = ctx->findApproximateKeylessTexture(desc);
1370 } else {
1371 entry = ctx->lockKeylessTexture(desc);
1372 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001373 } else {
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001374 uint32_t p0, p1;
reed@google.comac10a2d2010-12-22 21:39:39 +00001375 p0 = bitmap.getGenerationID();
1376 p1 = bitmap.pixelRefOffset();
reed@google.comac10a2d2010-12-22 21:39:39 +00001377
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001378 GrTextureKey key(p0, p1, bitmap.width(), bitmap.height());
1379 entry = ctx->findAndLockTexture(&key, sampler);
reed@google.comac10a2d2010-12-22 21:39:39 +00001380
reed@google.comac10a2d2010-12-22 21:39:39 +00001381 if (NULL == entry) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001382 entry = sk_gr_create_bitmap_texture(ctx, &key, sampler, bitmap);
1383 if (NULL == entry) {
1384 GrPrintf("---- failed to create texture for cache [%d %d]\n",
1385 bitmap.width(), bitmap.height());
1386 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001387 }
1388 }
1389
1390 if (NULL != entry) {
1391 newTexture = entry->texture();
reed@google.comac10a2d2010-12-22 21:39:39 +00001392 if (texture) {
1393 *texture = newTexture;
1394 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001395 }
1396 return (TexCache*)entry;
1397}
1398
1399void SkGpuDevice::unlockCachedTexture(TexCache* cache) {
1400 this->context()->unlockTexture((GrTextureEntry*)cache);
1401}
1402
reed@google.com7b201d22011-01-11 18:59:23 +00001403///////////////////////////////////////////////////////////////////////////////
1404
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001405SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context,
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001406 GrRenderTarget* rootRenderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001407 GrAssert(NULL != context);
1408 GrAssert(NULL != rootRenderTarget);
1409
1410 // check this now rather than passing this value to SkGpuDevice cons.
1411 // we want the rt that is bound *now* in the 3D API, not the one
1412 // at the time of newDevice.
1413 if (SkGpuDevice::Current3DApiRenderTarget() == rootRenderTarget) {
1414 fRootRenderTarget = context->createRenderTargetFrom3DApiState();
1415 } else {
1416 fRootRenderTarget = rootRenderTarget;
1417 rootRenderTarget->ref();
1418 }
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001419
1420 fContext = context;
reed@google.com7b201d22011-01-11 18:59:23 +00001421 context->ref();
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001422
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001423 fRootTexture = NULL;
1424}
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001425
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001426SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, GrTexture* rootRenderTargetTexture) {
1427 GrAssert(NULL != context);
1428 GrAssert(NULL != rootRenderTargetTexture);
1429 GrAssert(NULL != rootRenderTargetTexture->asRenderTarget());
1430
1431 fRootTexture = rootRenderTargetTexture;
1432 rootRenderTargetTexture->ref();
1433
1434 fRootRenderTarget = rootRenderTargetTexture->asRenderTarget();
1435 fRootRenderTarget->ref();
1436
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001437 fContext = context;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001438 context->ref();
reed@google.com7b201d22011-01-11 18:59:23 +00001439}
1440
1441SkGpuDeviceFactory::~SkGpuDeviceFactory() {
1442 fContext->unref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001443 fRootRenderTarget->unref();
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001444 GrSafeUnref(fRootTexture);
reed@google.com7b201d22011-01-11 18:59:23 +00001445}
1446
1447SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
1448 int width, int height,
1449 bool isOpaque, bool isLayer) {
1450 SkBitmap bm;
1451 bm.setConfig(config, width, height);
1452 bm.setIsOpaque(isOpaque);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001453 return new SkGpuDevice(fContext, bm, isLayer ? NULL : fRootRenderTarget);
reed@google.com7b201d22011-01-11 18:59:23 +00001454}