blob: 624cc68987dafb38cefcb7bd87a0ee55adc5a448 [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,
109 GrRenderTarget* renderTargetOrNull)
110 : SkDevice(NULL, bitmap, (NULL == renderTargetOrNull)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000111
112 fNeedPrepareRenderTarget = false;
113 fDrawProcs = NULL;
114
reed@google.com7b201d22011-01-11 18:59:23 +0000115 fContext = context;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000116 fContext->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000117
118 fCache = NULL;
119 fTexture = NULL;
120 fRenderTarget = NULL;
121 fNeedClear = false;
122
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000123 if (NULL == renderTargetOrNull) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000124 SkBitmap::Config c = bitmap.config();
125 if (c != SkBitmap::kRGB_565_Config) {
126 c = SkBitmap::kARGB_8888_Config;
127 }
128 SkBitmap bm;
129 bm.setConfig(c, this->width(), this->height());
130
131#if CACHE_LAYER_TEXTURES
132
133 fCache = this->lockCachedTexture(bm, GrSamplerState::ClampNoFilter(),
134 &fTexture, true);
135 if (fCache) {
136 SkASSERT(NULL != fTexture);
bsalomon@google.com1da07462011-03-10 14:51:57 +0000137 SkASSERT(NULL != fTexture->asRenderTarget());
reed@google.comac10a2d2010-12-22 21:39:39 +0000138 }
139#else
bsalomon@google.combb7f0762011-05-17 18:02:35 +0000140 const GrTextureDesc desc = {
141 kRenderTarget_GrTextureFlagBit,
142 kNone_GrAALevel,
reed@google.comac10a2d2010-12-22 21:39:39 +0000143 this->width(),
144 this->height(),
145 SkGr::Bitmap2PixelConfig(bm)
146 };
147
148 fTexture = fContext->createUncachedTexture(desc, NULL, 0);
149#endif
150 if (NULL != fTexture) {
151 fRenderTarget = fTexture->asRenderTarget();
152
153 GrAssert(NULL != fRenderTarget);
154
155 // we defer the actual clear until our gainFocus()
156 fNeedClear = true;
157
158 // wrap the bitmap with a pixelref to expose our texture
159 SkGrTexturePixelRef* pr = new SkGrTexturePixelRef(fTexture);
160 this->setPixelRef(pr, 0)->unref();
161 } else {
162 GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
163 this->width(), this->height());
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000164 GrAssert(false);
reed@google.comac10a2d2010-12-22 21:39:39 +0000165 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000166 } else {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000167 if (Current3DApiRenderTarget() == renderTargetOrNull) {
168 fRenderTarget = fContext->createRenderTargetFrom3DApiState();
169 } else {
170 fRenderTarget = renderTargetOrNull;
171 fRenderTarget->ref();
172 }
173 SkGrRenderTargetPixelRef* pr = new SkGrRenderTargetPixelRef(fRenderTarget);
174 this->setPixelRef(pr, 0)->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000175 }
176}
177
178SkGpuDevice::~SkGpuDevice() {
179 if (fDrawProcs) {
180 delete fDrawProcs;
181 }
182
183 if (fCache) {
184 GrAssert(NULL != fTexture);
185 GrAssert(fRenderTarget == fTexture->asRenderTarget());
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000186 fContext->unlockTexture((GrTextureEntry*)fCache);
reed@google.comac10a2d2010-12-22 21:39:39 +0000187 } else if (NULL != fTexture) {
188 GrAssert(!CACHE_LAYER_TEXTURES);
189 GrAssert(fRenderTarget == fTexture->asRenderTarget());
190 fTexture->unref();
191 } else if (NULL != fRenderTarget) {
192 fRenderTarget->unref();
193 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000194 fContext->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000195}
196
reed@google.comac10a2d2010-12-22 21:39:39 +0000197intptr_t SkGpuDevice::getLayerTextureHandle() const {
198 if (fTexture) {
199 return fTexture->getTextureHandle();
200 } else {
201 return 0;
202 }
203}
mike@reedtribe.orgea4ac972011-04-26 11:48:33 +0000204
205SkDeviceFactory* SkGpuDevice::onNewDeviceFactory() {
206 return SkNEW_ARGS(SkGpuDeviceFactory, (fContext, fRenderTarget));
207}
208
reed@google.comac10a2d2010-12-22 21:39:39 +0000209///////////////////////////////////////////////////////////////////////////////
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
Scroggo813c33c2011-04-07 20:56:21 +0000235 tmp.lockPixels();
reed@google.comac10a2d2010-12-22 21:39:39 +0000236
Scroggoeb176032011-04-07 21:11:49 +0000237 bool read = fContext->readRenderTargetPixels(fRenderTarget,
238 bounds.fLeft, bounds.fTop,
239 bounds.width(), bounds.height(),
240 kRGBA_8888_GrPixelConfig,
241 tmp.getPixels());
Scroggo813c33c2011-04-07 20:56:21 +0000242 tmp.unlockPixels();
243 if (!read) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000244 return false;
245 }
246
247 tmp.swap(*bitmap);
248 return true;
249}
250
251void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y) {
252 SkAutoLockPixels alp(bitmap);
253 if (!bitmap.readyToDraw()) {
254 return;
255 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000256 GrPixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(),
257 bitmap.isOpaque());
reed@google.comac10a2d2010-12-22 21:39:39 +0000258 fContext->setRenderTarget(fRenderTarget);
259 // we aren't setting the clip or matrix, so mark as dirty
260 // we don't need to set them for this call and don't have them anyway
261 fNeedPrepareRenderTarget = true;
262
263 fContext->writePixels(x, y, bitmap.width(), bitmap.height(),
264 config, bitmap.getPixels(), bitmap.rowBytes());
265}
266
267///////////////////////////////////////////////////////////////////////////////
268
269static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000270 const SkClipStack& clipStack,
reed@google.com6f8f2922011-03-04 22:27:10 +0000271 const SkRegion& clipRegion,
272 const SkIPoint& origin) {
bsalomon@google.comcc4dac32011-05-10 13:52:42 +0000273 context->setMatrix(matrix);
reed@google.comac10a2d2010-12-22 21:39:39 +0000274
275 SkGrClipIterator iter;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000276 iter.reset(clipStack);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000277 const SkIRect& skBounds = clipRegion.getBounds();
278 GrRect bounds;
279 bounds.setLTRB(GrIntToScalar(skBounds.fLeft),
280 GrIntToScalar(skBounds.fTop),
281 GrIntToScalar(skBounds.fRight),
282 GrIntToScalar(skBounds.fBottom));
reed@google.com6f8f2922011-03-04 22:27:10 +0000283 GrClip grc(&iter, GrIntToScalar(-origin.x()), GrIntToScalar(-origin.y()),
284 &bounds);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000285 context->setClip(grc);
reed@google.comac10a2d2010-12-22 21:39:39 +0000286}
287
288// call this ever each draw call, to ensure that the context reflects our state,
289// and not the state from some other canvas/device
290void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) {
291 if (fNeedPrepareRenderTarget ||
bsalomon@google.com5782d712011-01-21 21:03:59 +0000292 fContext->getRenderTarget() != fRenderTarget) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000293
294 fContext->setRenderTarget(fRenderTarget);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000295 SkASSERT(draw.fClipStack);
296 convert_matrixclip(fContext, *draw.fMatrix,
reed@google.com6f8f2922011-03-04 22:27:10 +0000297 *draw.fClipStack, *draw.fClip, this->getOrigin());
reed@google.comac10a2d2010-12-22 21:39:39 +0000298 fNeedPrepareRenderTarget = false;
299 }
300}
301
reed@google.com46799cd2011-02-22 20:56:26 +0000302void SkGpuDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& clip,
303 const SkClipStack& clipStack) {
304 this->INHERITED::setMatrixClip(matrix, clip, clipStack);
bsalomon@google.coma7bf6e22011-04-11 19:20:46 +0000305 // We don't need to set them now because the context may not reflect this device.
306 fNeedPrepareRenderTarget = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000307}
308
309void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000310 const SkRegion& clip, const SkClipStack& clipStack) {
311
reed@google.comac10a2d2010-12-22 21:39:39 +0000312 fContext->setRenderTarget(fRenderTarget);
313
bsalomon@google.comd302f142011-03-03 13:54:13 +0000314 this->INHERITED::gainFocus(canvas, matrix, clip, clipStack);
reed@google.comac10a2d2010-12-22 21:39:39 +0000315
reed@google.com6f8f2922011-03-04 22:27:10 +0000316 convert_matrixclip(fContext, matrix, clipStack, clip, this->getOrigin());
reed@google.comac10a2d2010-12-22 21:39:39 +0000317
318 if (fNeedClear) {
bsalomon@google.com31a58402011-04-27 21:00:02 +0000319 fContext->clear(NULL, 0x0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000320 fNeedClear = false;
321 }
322}
323
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000324bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000325 if (NULL != fTexture) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000326 paint->setTexture(kBitmapTextureIdx, fTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +0000327 return true;
328 }
329 return false;
330}
331
332///////////////////////////////////////////////////////////////////////////////
333
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000334SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch);
335SK_COMPILE_ASSERT(SkShader::kDefault_BitmapType == 1, shader_type_mismatch);
336SK_COMPILE_ASSERT(SkShader::kRadial_BitmapType == 2, shader_type_mismatch);
337SK_COMPILE_ASSERT(SkShader::kSweep_BitmapType == 3, shader_type_mismatch);
338SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4,
339 shader_type_mismatch);
340SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 4, shader_type_mismatch);
reed@google.comac10a2d2010-12-22 21:39:39 +0000341
bsalomon@google.com5782d712011-01-21 21:03:59 +0000342static const GrSamplerState::SampleMode sk_bmp_type_to_sample_mode[] = {
343 (GrSamplerState::SampleMode) -1, // kNone_BitmapType
344 GrSamplerState::kNormal_SampleMode, // kDefault_BitmapType
345 GrSamplerState::kRadial_SampleMode, // kRadial_BitmapType
346 GrSamplerState::kSweep_SampleMode, // kSweep_BitmapType
347 GrSamplerState::kRadial2_SampleMode, // kTwoPointRadial_BitmapType
348};
349
350bool SkGpuDevice::skPaint2GrPaintNoShader(const SkPaint& skPaint,
351 bool justAlpha,
Scroggod757df22011-05-16 13:11:16 +0000352 GrPaint* grPaint,
353 bool constantColor) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000354
355 grPaint->fDither = skPaint.isDither();
356 grPaint->fAntiAlias = skPaint.isAntiAlias();
357
358 SkXfermode::Coeff sm = SkXfermode::kOne_Coeff;
359 SkXfermode::Coeff dm = SkXfermode::kISA_Coeff;
360
361 SkXfermode* mode = skPaint.getXfermode();
362 if (mode) {
363 if (!mode->asCoeff(&sm, &dm)) {
reed@google.com1a2e8d22011-01-21 22:08:29 +0000364 SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
bsalomon@google.com5782d712011-01-21 21:03:59 +0000365#if 0
366 return false;
367#endif
368 }
369 }
370 grPaint->fSrcBlendCoeff = sk_blend_to_grblend(sm);
371 grPaint->fDstBlendCoeff = sk_blend_to_grblend(dm);
372
373 if (justAlpha) {
374 uint8_t alpha = skPaint.getAlpha();
375 grPaint->fColor = GrColorPackRGBA(alpha, alpha, alpha, alpha);
Scroggod757df22011-05-16 13:11:16 +0000376 // justAlpha is currently set to true only if there is a texture,
377 // so constantColor should not also be true.
378 GrAssert(!constantColor);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000379 } else {
380 grPaint->fColor = SkGr::SkColor2GrColor(skPaint.getColor());
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000381 grPaint->setTexture(kShaderTextureIdx, NULL);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000382 }
Scroggo97c88c22011-05-11 14:05:25 +0000383 SkColorFilter* colorFilter = skPaint.getColorFilter();
384 SkColor color;
385 SkXfermode::Mode filterMode;
386 if (colorFilter != NULL && colorFilter->asColorMode(&color, &filterMode)) {
Scroggod757df22011-05-16 13:11:16 +0000387 if (!constantColor) {
388 grPaint->fColorFilterColor = SkGr::SkColor2GrColor(color);
389 grPaint->fColorFilterXfermode = filterMode;
390 return true;
391 }
392 SkColor filtered = colorFilter->filterColor(skPaint.getColor());
393 grPaint->fColor = SkGr::SkColor2GrColor(filtered);
Scroggo97c88c22011-05-11 14:05:25 +0000394 }
Scroggod757df22011-05-16 13:11:16 +0000395 grPaint->resetColorFilter();
bsalomon@google.com5782d712011-01-21 21:03:59 +0000396 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000397}
398
bsalomon@google.com5782d712011-01-21 21:03:59 +0000399bool SkGpuDevice::skPaint2GrPaintShader(const SkPaint& skPaint,
400 SkAutoCachedTexture* act,
401 const SkMatrix& ctm,
Scroggod757df22011-05-16 13:11:16 +0000402 GrPaint* grPaint,
403 bool constantColor) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000404
bsalomon@google.com5782d712011-01-21 21:03:59 +0000405 SkASSERT(NULL != act);
reed@google.comac10a2d2010-12-22 21:39:39 +0000406
bsalomon@google.com5782d712011-01-21 21:03:59 +0000407 SkShader* shader = skPaint.getShader();
reed@google.comac10a2d2010-12-22 21:39:39 +0000408 if (NULL == shader) {
Scroggod757df22011-05-16 13:11:16 +0000409 return this->skPaint2GrPaintNoShader(skPaint,
410 false,
411 grPaint,
412 constantColor);
413 } else if (!this->skPaint2GrPaintNoShader(skPaint, true, grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000414 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000415 }
416
bsalomon@google.com5782d712011-01-21 21:03:59 +0000417 SkPaint noAlphaPaint(skPaint);
418 noAlphaPaint.setAlpha(255);
419 shader->setContext(this->accessBitmap(false), noAlphaPaint, ctm);
reed@google.comac10a2d2010-12-22 21:39:39 +0000420
reed@google.comac10a2d2010-12-22 21:39:39 +0000421 SkBitmap bitmap;
422 SkMatrix matrix;
423 SkShader::TileMode tileModes[2];
424 SkScalar twoPointParams[3];
425 SkShader::BitmapType bmptype = shader->asABitmap(&bitmap, &matrix,
426 tileModes, twoPointParams);
427
bsalomon@google.com5782d712011-01-21 21:03:59 +0000428 GrSamplerState::SampleMode sampleMode = sk_bmp_type_to_sample_mode[bmptype];
429 if (-1 == sampleMode) {
430 SkDebugf("shader->asABitmap() == kNone_BitmapType\n");
431 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000432 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000433 GrSamplerState* sampler = grPaint->getTextureSampler(kShaderTextureIdx);
434 sampler->setSampleMode(sampleMode);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000435 if (skPaint.isFilterBitmap()) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000436 sampler->setFilter(GrSamplerState::kBilinear_Filter);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000437 } else {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000438 sampler->setFilter(GrSamplerState::kNearest_Filter);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000439 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000440 sampler->setWrapX(sk_tile_mode_to_grwrap(tileModes[0]));
441 sampler->setWrapY(sk_tile_mode_to_grwrap(tileModes[1]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000442 if (GrSamplerState::kRadial2_SampleMode == sampleMode) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000443 sampler->setRadial2Params(twoPointParams[0],
444 twoPointParams[1],
445 twoPointParams[2] < 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000446 }
447
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000448 GrTexture* texture = act->set(this, bitmap, *sampler);
reed@google.comac10a2d2010-12-22 21:39:39 +0000449 if (NULL == texture) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000450 SkDebugf("Couldn't convert bitmap to texture.\n");
451 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000452 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000453 grPaint->setTexture(kShaderTextureIdx, texture);
reed@google.comac10a2d2010-12-22 21:39:39 +0000454
455 // since our texture coords will be in local space, we wack the texture
456 // matrix to map them back into 0...1 before we load it
457 SkMatrix localM;
458 if (shader->getLocalMatrix(&localM)) {
459 SkMatrix inverse;
460 if (localM.invert(&inverse)) {
461 matrix.preConcat(inverse);
462 }
463 }
464 if (SkShader::kDefault_BitmapType == bmptype) {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000465 GrScalar sx = GrFixedToScalar(GR_Fixed1 / bitmap.width());
466 GrScalar sy = GrFixedToScalar(GR_Fixed1 / bitmap.height());
reed@google.comac10a2d2010-12-22 21:39:39 +0000467 matrix.postScale(sx, sy);
reed@google.comac10a2d2010-12-22 21:39:39 +0000468 } else if (SkShader::kRadial_BitmapType == bmptype) {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000469 GrScalar s = GrFixedToScalar(GR_Fixed1 / bitmap.width());
reed@google.comac10a2d2010-12-22 21:39:39 +0000470 matrix.postScale(s, s);
471 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000472 sampler->setMatrix(matrix);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000473
474 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000475}
476
477///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com5782d712011-01-21 21:03:59 +0000478
479class SkPositionSource {
480public:
481 SkPositionSource(const SkPoint* points, int count)
482 : fPoints(points), fCount(count) {}
483
484 int count() const { return fCount; }
485
486 void writeValue(int i, GrPoint* dstPosition) const {
487 SkASSERT(i < fCount);
488 dstPosition->fX = SkScalarToGrScalar(fPoints[i].fX);
489 dstPosition->fY = SkScalarToGrScalar(fPoints[i].fY);
490 }
491private:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000492 const SkPoint* fPoints;
bsalomon@google.com19628322011-02-03 21:30:17 +0000493 int fCount;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000494};
495
496class SkTexCoordSource {
497public:
498 SkTexCoordSource(const SkPoint* coords)
499 : fCoords(coords) {}
500
501 void writeValue(int i, GrPoint* dstCoord) const {
502 dstCoord->fX = SkScalarToGrScalar(fCoords[i].fX);
503 dstCoord->fY = SkScalarToGrScalar(fCoords[i].fY);
504 }
505private:
506 const SkPoint* fCoords;
507};
508
509class SkColorSource {
510public:
511 SkColorSource(const SkColor* colors) : fColors(colors) {}
512
513 void writeValue(int i, GrColor* dstColor) const {
514 *dstColor = SkGr::SkColor2GrColor(fColors[i]);
515 }
516private:
517 const SkColor* fColors;
518};
519
520class SkIndexSource {
521public:
522 SkIndexSource(const uint16_t* indices, int count)
523 : fIndices(indices), fCount(count) {
524 }
525
526 int count() const { return fCount; }
527
528 void writeValue(int i, uint16_t* dstIndex) const {
529 *dstIndex = fIndices[i];
530 }
531
532private:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000533 const uint16_t* fIndices;
bsalomon@google.com19628322011-02-03 21:30:17 +0000534 int fCount;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000535};
536
537///////////////////////////////////////////////////////////////////////////////
538
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000539#if 0 // not currently being used so don't compile,
540
bsalomon@google.com5782d712011-01-21 21:03:59 +0000541// can be used for positions or texture coordinates
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000542
bsalomon@google.com5782d712011-01-21 21:03:59 +0000543class SkRectFanSource {
544public:
545 SkRectFanSource(const SkRect& rect) : fRect(rect) {}
546
547 int count() const { return 4; }
548
549 void writeValue(int i, GrPoint* dstPoint) const {
550 SkASSERT(i < 4);
551 dstPoint->fX = SkScalarToGrScalar((i % 3) ? fRect.fRight :
552 fRect.fLeft);
553 dstPoint->fY = SkScalarToGrScalar((i < 2) ? fRect.fTop :
554 fRect.fBottom);
555 }
556private:
557 const SkRect& fRect;
558};
559
560class SkIRectFanSource {
561public:
562 SkIRectFanSource(const SkIRect& rect) : fRect(rect) {}
563
564 int count() const { return 4; }
565
566 void writeValue(int i, GrPoint* dstPoint) const {
567 SkASSERT(i < 4);
568 dstPoint->fX = (i % 3) ? GrIntToScalar(fRect.fRight) :
569 GrIntToScalar(fRect.fLeft);
570 dstPoint->fY = (i < 2) ? GrIntToScalar(fRect.fTop) :
571 GrIntToScalar(fRect.fBottom);
572 }
573private:
574 const SkIRect& fRect;
575};
576
577class SkMatRectFanSource {
578public:
579 SkMatRectFanSource(const SkRect& rect, const SkMatrix& matrix)
580 : fRect(rect), fMatrix(matrix) {}
581
582 int count() const { return 4; }
583
584 void writeValue(int i, GrPoint* dstPoint) const {
585 SkASSERT(i < 4);
586
587#if SK_SCALAR_IS_GR_SCALAR
588 fMatrix.mapXY((i % 3) ? fRect.fRight : fRect.fLeft,
589 (i < 2) ? fRect.fTop : fRect.fBottom,
590 (SkPoint*)dstPoint);
591#else
592 SkPoint dst;
593 fMatrix.mapXY((i % 3) ? fRect.fRight : fRect.fLeft,
594 (i < 2) ? fRect.fTop : fRect.fBottom,
595 &dst);
596 dstPoint->fX = SkScalarToGrScalar(dst.fX);
597 dstPoint->fY = SkScalarToGrScalar(dst.fY);
598#endif
599 }
600private:
601 const SkRect& fRect;
602 const SkMatrix& fMatrix;
603};
604
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000605#endif
606
reed@google.comac10a2d2010-12-22 21:39:39 +0000607///////////////////////////////////////////////////////////////////////////////
608
bsalomon@google.com398109c2011-04-14 18:40:27 +0000609void SkGpuDevice::clear(SkColor color) {
bsalomon@google.com31a58402011-04-27 21:00:02 +0000610 fContext->clear(NULL, color);
bsalomon@google.com398109c2011-04-14 18:40:27 +0000611}
612
reed@google.comac10a2d2010-12-22 21:39:39 +0000613void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
614 CHECK_SHOULD_DRAW(draw);
615
bsalomon@google.com5782d712011-01-21 21:03:59 +0000616 GrPaint grPaint;
617 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +0000618 if (!this->skPaint2GrPaintShader(paint,
619 &act,
620 *draw.fMatrix,
621 &grPaint,
622 true)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000623 return;
624 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000625
626 fContext->drawPaint(grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000627}
628
629// must be in SkCanvas::PointMode order
bsalomon@google.comffca4002011-02-22 20:34:01 +0000630static const GrPrimitiveType gPointMode2PrimtiveType[] = {
631 kPoints_PrimitiveType,
632 kLines_PrimitiveType,
633 kLineStrip_PrimitiveType
reed@google.comac10a2d2010-12-22 21:39:39 +0000634};
635
636void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000637 size_t count, const SkPoint pts[], const SkPaint& paint) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000638 CHECK_SHOULD_DRAW(draw);
639
640 SkScalar width = paint.getStrokeWidth();
641 if (width < 0) {
642 return;
643 }
644
645 // we only handle hairlines here, else we let the SkDraw call our drawPath()
646 if (width > 0) {
647 draw.drawPoints(mode, count, pts, paint, true);
648 return;
649 }
650
bsalomon@google.com5782d712011-01-21 21:03:59 +0000651 GrPaint grPaint;
652 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +0000653 if (!this->skPaint2GrPaintShader(paint,
654 &act,
655 *draw.fMatrix,
656 &grPaint,
657 true)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000658 return;
659 }
660
reed@google.comac10a2d2010-12-22 21:39:39 +0000661#if SK_SCALAR_IS_GR_SCALAR
bsalomon@google.com5782d712011-01-21 21:03:59 +0000662 fContext->drawVertices(grPaint,
663 gPointMode2PrimtiveType[mode],
664 count,
665 (GrPoint*)pts,
666 NULL,
667 NULL,
668 NULL,
669 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000670#else
bsalomon@google.com5782d712011-01-21 21:03:59 +0000671 fContext->drawCustomVertices(grPaint,
672 gPointMode2PrimtiveType[mode],
673 SkPositionSource(pts, count));
reed@google.comac10a2d2010-12-22 21:39:39 +0000674#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000675}
676
reed@google.comc9aa5872011-04-05 21:05:37 +0000677///////////////////////////////////////////////////////////////////////////////
678
reed@google.comac10a2d2010-12-22 21:39:39 +0000679void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
680 const SkPaint& paint) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000681 CHECK_SHOULD_DRAW(draw);
682
683 bool doStroke = paint.getStyle() == SkPaint::kStroke_Style;
684 SkScalar width = paint.getStrokeWidth();
685
686 /*
687 We have special code for hairline strokes, miter-strokes, and fills.
688 Anything else we just call our path code.
689 */
690 bool usePath = doStroke && width > 0 &&
691 paint.getStrokeJoin() != SkPaint::kMiter_Join;
692 // another reason we might need to call drawPath...
693 if (paint.getMaskFilter()) {
694 usePath = true;
695 }
696
697 if (usePath) {
698 SkPath path;
699 path.addRect(rect);
700 this->drawPath(draw, path, paint, NULL, true);
701 return;
702 }
703
704 GrPaint grPaint;
705 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +0000706 if (!this->skPaint2GrPaintShader(paint,
707 &act,
708 *draw.fMatrix,
709 &grPaint,
710 true)) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000711 return;
712 }
reed@google.com20efde72011-05-09 17:00:02 +0000713 fContext->drawRect(grPaint, rect, doStroke ? width : -1);
reed@google.comac10a2d2010-12-22 21:39:39 +0000714}
715
reed@google.com69302852011-02-16 18:08:07 +0000716#include "SkMaskFilter.h"
717#include "SkBounder.h"
718
reed@google.com69302852011-02-16 18:08:07 +0000719static bool drawWithMaskFilter(GrContext* context, const SkPath& path,
720 SkMaskFilter* filter, const SkMatrix& matrix,
721 const SkRegion& clip, SkBounder* bounder,
722 GrPaint* grp) {
723 SkMask srcM, dstM;
724
725 if (!SkDraw::DrawToMask(path, &clip.getBounds(), filter, &matrix, &srcM,
726 SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
727 return false;
728 }
729
730 SkAutoMaskImage autoSrc(&srcM, false);
731
732 if (!filter->filterMask(&dstM, srcM, matrix, NULL)) {
733 return false;
734 }
735 // this will free-up dstM when we're done (allocated in filterMask())
736 SkAutoMaskImage autoDst(&dstM, false);
737
738 if (clip.quickReject(dstM.fBounds)) {
739 return false;
740 }
741 if (bounder && !bounder->doIRect(dstM.fBounds)) {
742 return false;
743 }
744
745 // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
746 // the current clip (and identity matrix) and grpaint settings
747
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000748 // used to compute inverse view, if necessary
749 GrMatrix ivm = context->getMatrix();
750
reed@google.com0c219b62011-02-16 21:31:18 +0000751 GrAutoMatrix avm(context, GrMatrix::I());
reed@google.com69302852011-02-16 18:08:07 +0000752
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000753 const GrTextureDesc desc = {
754 kNone_GrTextureFlags,
755 kNone_GrAALevel,
reed@google.com69302852011-02-16 18:08:07 +0000756 dstM.fBounds.width(),
757 dstM.fBounds.height(),
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000758 kAlpha_8_GrPixelConfig
reed@google.com69302852011-02-16 18:08:07 +0000759 };
760
761 GrTexture* texture = context->createUncachedTexture(desc, dstM.fImage,
762 dstM.fRowBytes);
763 if (NULL == texture) {
764 return false;
765 }
766
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000767 if (grp->hasTextureOrMask() && ivm.invert(&ivm)) {
768 grp->preConcatActiveSamplerMatrices(ivm);
769 }
770
771 static const int MASK_IDX = GrPaint::kMaxMasks - 1;
772 // we assume the last mask index is available for use
773 GrAssert(NULL == grp->getMask(MASK_IDX));
774 grp->setMask(MASK_IDX, texture);
reed@google.com0c219b62011-02-16 21:31:18 +0000775 texture->unref();
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000776 grp->getMaskSampler(MASK_IDX)->setClampNoFilter();
reed@google.com69302852011-02-16 18:08:07 +0000777
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000778 GrRect d;
779 d.setLTRB(GrIntToScalar(dstM.fBounds.fLeft),
reed@google.com0c219b62011-02-16 21:31:18 +0000780 GrIntToScalar(dstM.fBounds.fTop),
781 GrIntToScalar(dstM.fBounds.fRight),
782 GrIntToScalar(dstM.fBounds.fBottom));
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000783
784 GrMatrix m;
785 m.setTranslate(-dstM.fBounds.fLeft, -dstM.fBounds.fTop);
786 m.postIDiv(dstM.fBounds.width(), dstM.fBounds.height());
787 grp->getMaskSampler(MASK_IDX)->setMatrix(m);
788
789 context->drawRect(*grp, d);
reed@google.com69302852011-02-16 18:08:07 +0000790 return true;
791}
reed@google.com69302852011-02-16 18:08:07 +0000792
reed@google.com0c219b62011-02-16 21:31:18 +0000793void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
reed@google.comac10a2d2010-12-22 21:39:39 +0000794 const SkPaint& paint, const SkMatrix* prePathMatrix,
795 bool pathIsMutable) {
796 CHECK_SHOULD_DRAW(draw);
797
bsalomon@google.com5782d712011-01-21 21:03:59 +0000798 GrPaint grPaint;
799 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +0000800 if (!this->skPaint2GrPaintShader(paint,
801 &act,
802 *draw.fMatrix,
803 &grPaint,
804 true)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000805 return;
806 }
807
reed@google.com0c219b62011-02-16 21:31:18 +0000808 // BEGIN lift from SkDraw::drawPath()
809
810 SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
811 bool doFill = true;
812 SkPath tmpPath;
reed@google.comac10a2d2010-12-22 21:39:39 +0000813
814 if (prePathMatrix) {
reed@google.come3445642011-02-16 23:20:39 +0000815 SkPath* result = pathPtr;
reed@google.com0c219b62011-02-16 21:31:18 +0000816
reed@google.come3445642011-02-16 23:20:39 +0000817 if (!pathIsMutable) {
818 result = &tmpPath;
819 pathIsMutable = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000820 }
reed@google.come3445642011-02-16 23:20:39 +0000821 // should I push prePathMatrix on our MV stack temporarily, instead
822 // of applying it here? See SkDraw.cpp
823 pathPtr->transform(*prePathMatrix, result);
824 pathPtr = result;
reed@google.comac10a2d2010-12-22 21:39:39 +0000825 }
reed@google.com0c219b62011-02-16 21:31:18 +0000826 // at this point we're done with prePathMatrix
827 SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
reed@google.comac10a2d2010-12-22 21:39:39 +0000828
bsalomon@google.com04de7822011-03-25 18:04:43 +0000829 // This "if" is not part of the SkDraw::drawPath() lift.
830 // When we get a 1.0 wide stroke we hairline stroke it instead of creating
831 // a new stroked-path. This is motivated by canvas2D sites that draw
832 // lines as 1.0 wide stroked paths. We can consider doing an alpha-modulated-
833 // hairline for width < 1.0 when AA is enabled.
834 static const int gMatrixMask = ~(SkMatrix::kIdentity_Mask |
835 SkMatrix::kTranslate_Mask);
836 if (!paint.getPathEffect() &&
837 SkPaint::kStroke_Style == paint.getStyle() &&
838 !(draw.fMatrix->getType() & gMatrixMask) &&
839 SK_Scalar1 == paint.getStrokeWidth()) {
840 doFill = false;
841 }
842
843 if (doFill && (paint.getPathEffect() ||
844 paint.getStyle() != SkPaint::kFill_Style)) {
reed@google.com0c219b62011-02-16 21:31:18 +0000845 doFill = paint.getFillPath(*pathPtr, &tmpPath);
846 pathPtr = &tmpPath;
847 }
848
849 // END lift from SkDraw::drawPath()
850
reed@google.com69302852011-02-16 18:08:07 +0000851 if (paint.getMaskFilter()) {
reed@google.com0c219b62011-02-16 21:31:18 +0000852 // avoid possibly allocating a new path in transform if we can
853 SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
854
855 // transform the path into device space
reed@google.come3445642011-02-16 23:20:39 +0000856 pathPtr->transform(*draw.fMatrix, devPathPtr);
reed@google.com0c219b62011-02-16 21:31:18 +0000857
858 drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
reed@google.com69302852011-02-16 18:08:07 +0000859 *draw.fMatrix, *draw.fClip, draw.fBounder, &grPaint);
860 return;
861 }
reed@google.com69302852011-02-16 18:08:07 +0000862
bsalomon@google.comffca4002011-02-22 20:34:01 +0000863 GrPathFill fill = kHairLine_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000864
reed@google.com0c219b62011-02-16 21:31:18 +0000865 if (doFill) {
866 switch (pathPtr->getFillType()) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000867 case SkPath::kWinding_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000868 fill = kWinding_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000869 break;
870 case SkPath::kEvenOdd_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000871 fill = kEvenOdd_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000872 break;
873 case SkPath::kInverseWinding_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000874 fill = kInverseWinding_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000875 break;
876 case SkPath::kInverseEvenOdd_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000877 fill = kInverseEvenOdd_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000878 break;
879 default:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000880 SkDebugf("Unsupported path fill type\n");
reed@google.comac10a2d2010-12-22 21:39:39 +0000881 return;
882 }
883 }
884
reed@google.com07f3ee12011-05-16 17:21:57 +0000885 fContext->drawPath(grPaint, *pathPtr, fill);
reed@google.comac10a2d2010-12-22 21:39:39 +0000886}
887
reed@google.comac10a2d2010-12-22 21:39:39 +0000888void SkGpuDevice::drawBitmap(const SkDraw& draw,
889 const SkBitmap& bitmap,
890 const SkIRect* srcRectPtr,
891 const SkMatrix& m,
892 const SkPaint& paint) {
893 CHECK_SHOULD_DRAW(draw);
894
895 SkIRect srcRect;
896 if (NULL == srcRectPtr) {
897 srcRect.set(0, 0, bitmap.width(), bitmap.height());
898 } else {
899 srcRect = *srcRectPtr;
900 }
901
bsalomon@google.com5782d712011-01-21 21:03:59 +0000902 GrPaint grPaint;
Scroggod757df22011-05-16 13:11:16 +0000903 if (!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000904 return;
905 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000906 GrSamplerState* sampler = grPaint.getTextureSampler(kBitmapTextureIdx);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000907 if (paint.isFilterBitmap()) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000908 sampler->setFilter(GrSamplerState::kBilinear_Filter);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000909 } else {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000910 sampler->setFilter(GrSamplerState::kNearest_Filter);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000911 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000912
reed@google.com02a7e6c2011-01-28 21:21:49 +0000913 const int maxTextureDim = fContext->getMaxTextureDimension();
914 if (bitmap.getTexture() || (bitmap.width() <= maxTextureDim &&
915 bitmap.height() <= maxTextureDim)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000916 // take the fast case
bsalomon@google.com5782d712011-01-21 21:03:59 +0000917 this->internalDrawBitmap(draw, bitmap, srcRect, m, &grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000918 return;
919 }
920
921 // undo the translate done by SkCanvas
922 int DX = SkMax32(0, srcRect.fLeft);
923 int DY = SkMax32(0, srcRect.fTop);
924 // compute clip bounds in local coordinates
925 SkIRect clipRect;
926 {
927 SkRect r;
928 r.set(draw.fClip->getBounds());
929 SkMatrix matrix, inverse;
930 matrix.setConcat(*draw.fMatrix, m);
931 if (!matrix.invert(&inverse)) {
932 return;
933 }
934 inverse.mapRect(&r);
935 r.roundOut(&clipRect);
936 // apply the canvas' translate to our local clip
937 clipRect.offset(DX, DY);
938 }
939
reed@google.com02a7e6c2011-01-28 21:21:49 +0000940 int nx = bitmap.width() / maxTextureDim;
941 int ny = bitmap.height() / maxTextureDim;
reed@google.comac10a2d2010-12-22 21:39:39 +0000942 for (int x = 0; x <= nx; x++) {
943 for (int y = 0; y <= ny; y++) {
944 SkIRect tileR;
reed@google.com02a7e6c2011-01-28 21:21:49 +0000945 tileR.set(x * maxTextureDim, y * maxTextureDim,
946 (x + 1) * maxTextureDim, (y + 1) * maxTextureDim);
reed@google.comac10a2d2010-12-22 21:39:39 +0000947 if (!SkIRect::Intersects(tileR, clipRect)) {
948 continue;
949 }
950
951 SkIRect srcR = tileR;
952 if (!srcR.intersect(srcRect)) {
953 continue;
954 }
955
956 SkBitmap tmpB;
957 if (bitmap.extractSubset(&tmpB, tileR)) {
958 // now offset it to make it "local" to our tmp bitmap
959 srcR.offset(-tileR.fLeft, -tileR.fTop);
960
961 SkMatrix tmpM(m);
962 {
963 int dx = tileR.fLeft - DX + SkMax32(0, srcR.fLeft);
964 int dy = tileR.fTop - DY + SkMax32(0, srcR.fTop);
965 tmpM.preTranslate(SkIntToScalar(dx), SkIntToScalar(dy));
966 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000967 this->internalDrawBitmap(draw, tmpB, srcR, tmpM, &grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000968 }
969 }
970 }
971}
972
973/*
974 * This is called by drawBitmap(), which has to handle images that may be too
975 * large to be represented by a single texture.
976 *
bsalomon@google.com5782d712011-01-21 21:03:59 +0000977 * internalDrawBitmap assumes that the specified bitmap will fit in a texture
978 * and that non-texture portion of the GrPaint has already been setup.
reed@google.comac10a2d2010-12-22 21:39:39 +0000979 */
980void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
981 const SkBitmap& bitmap,
982 const SkIRect& srcRect,
983 const SkMatrix& m,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000984 GrPaint* grPaint) {
reed@google.com02a7e6c2011-01-28 21:21:49 +0000985 SkASSERT(bitmap.width() <= fContext->getMaxTextureDimension() &&
986 bitmap.height() <= fContext->getMaxTextureDimension());
reed@google.comac10a2d2010-12-22 21:39:39 +0000987
988 SkAutoLockPixels alp(bitmap);
989 if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
990 return;
991 }
992
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000993 GrSamplerState* sampler = grPaint->getTextureSampler(kBitmapTextureIdx);
994
995 sampler->setWrapX(GrSamplerState::kClamp_WrapMode);
996 sampler->setWrapY(GrSamplerState::kClamp_WrapMode);
997 sampler->setSampleMode(GrSamplerState::kNormal_SampleMode);
998 sampler->setMatrix(GrMatrix::I());
reed@google.comac10a2d2010-12-22 21:39:39 +0000999
1000 GrTexture* texture;
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001001 SkAutoCachedTexture act(this, bitmap, *sampler, &texture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001002 if (NULL == texture) {
1003 return;
1004 }
1005
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001006 grPaint->setTexture(kShaderTextureIdx, texture);
reed@google.com46799cd2011-02-22 20:56:26 +00001007
reed@google.com20efde72011-05-09 17:00:02 +00001008 GrRect dstRect = SkRect::MakeWH(GrIntToScalar(srcRect.width()),
1009 GrIntToScalar(srcRect.height()));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001010 GrRect paintRect;
junov@google.com6acc9b32011-05-16 18:32:07 +00001011 paintRect.setLTRB(GrFixedToScalar((srcRect.fLeft << 16) / bitmap.width()),
1012 GrFixedToScalar((srcRect.fTop << 16) / bitmap.height()),
1013 GrFixedToScalar((srcRect.fRight << 16) / bitmap.width()),
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001014 GrFixedToScalar((srcRect.fBottom << 16) / bitmap.height()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001015
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001016 if (GrSamplerState::kNearest_Filter != sampler->getFilter() &&
junov@google.com6acc9b32011-05-16 18:32:07 +00001017 (srcRect.width() < bitmap.width() ||
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001018 srcRect.height() < bitmap.height())) {
junov@google.com6acc9b32011-05-16 18:32:07 +00001019 // If drawing a subrect of the bitmap and filtering is enabled,
1020 // use a constrained texture domain to avoid color bleeding
1021 GrScalar left, top, right, bottom;
1022 if (srcRect.width() > 1) {
1023 GrScalar border = GR_ScalarHalf / bitmap.width();
1024 left = paintRect.left() + border;
1025 right = paintRect.right() - border;
1026 } else {
1027 left = right = GrScalarHalf(paintRect.left() + paintRect.right());
1028 }
1029 if (srcRect.height() > 1) {
1030 GrScalar border = GR_ScalarHalf / bitmap.height();
1031 top = paintRect.top() + border;
1032 bottom = paintRect.bottom() - border;
1033 } else {
1034 top = bottom = GrScalarHalf(paintRect.top() + paintRect.bottom());
1035 }
1036 GrRect textureDomain;
1037 textureDomain.setLTRB(left, top, right, bottom);
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001038 sampler->setTextureDomain(textureDomain);
junov@google.com6acc9b32011-05-16 18:32:07 +00001039 }
1040
bsalomon@google.comcc4dac32011-05-10 13:52:42 +00001041 fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m);
reed@google.comac10a2d2010-12-22 21:39:39 +00001042}
1043
1044void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
1045 int left, int top, const SkPaint& paint) {
1046 CHECK_SHOULD_DRAW(draw);
1047
1048 SkAutoLockPixels alp(bitmap);
1049 if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
1050 return;
1051 }
1052
bsalomon@google.com5782d712011-01-21 21:03:59 +00001053 GrPaint grPaint;
Scroggod757df22011-05-16 13:11:16 +00001054 if(!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001055 return;
1056 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001057
bsalomon@google.com5782d712011-01-21 21:03:59 +00001058 GrAutoMatrix avm(fContext, GrMatrix::I());
1059
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001060 GrSamplerState* sampler = grPaint.getTextureSampler(kBitmapTextureIdx);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001061
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001062 GrTexture* texture;
1063 sampler->setClampNoFilter();
1064 SkAutoCachedTexture act(this, bitmap, *sampler, &texture);
1065
1066 grPaint.setTexture(kBitmapTextureIdx, texture);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001067
bsalomon@google.com5782d712011-01-21 21:03:59 +00001068 fContext->drawRectToRect(grPaint,
reed@google.com20efde72011-05-09 17:00:02 +00001069 GrRect::MakeXYWH(GrIntToScalar(left),
1070 GrIntToScalar(top),
1071 GrIntToScalar(bitmap.width()),
1072 GrIntToScalar(bitmap.height())),
1073 GrRect::MakeWH(GR_Scalar1, GR_Scalar1));
reed@google.comac10a2d2010-12-22 21:39:39 +00001074}
1075
1076void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* dev,
1077 int x, int y, const SkPaint& paint) {
1078 CHECK_SHOULD_DRAW(draw);
1079
bsalomon@google.com5782d712011-01-21 21:03:59 +00001080 GrPaint grPaint;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001081 if (!((SkGpuDevice*)dev)->bindDeviceAsTexture(&grPaint) ||
Scroggod757df22011-05-16 13:11:16 +00001082 !this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001083 return;
reed@google.comac10a2d2010-12-22 21:39:39 +00001084 }
bsalomon@google.com5782d712011-01-21 21:03:59 +00001085
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001086 SkASSERT(NULL != grPaint.getTexture(0));
bsalomon@google.com5782d712011-01-21 21:03:59 +00001087
1088 const SkBitmap& bm = dev->accessBitmap(false);
1089 int w = bm.width();
1090 int h = bm.height();
1091
1092 GrAutoMatrix avm(fContext, GrMatrix::I());
1093
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001094 grPaint.getTextureSampler(kBitmapTextureIdx)->setClampNoFilter();
bsalomon@google.com5782d712011-01-21 21:03:59 +00001095
1096 fContext->drawRectToRect(grPaint,
reed@google.com20efde72011-05-09 17:00:02 +00001097 GrRect::MakeXYWH(GrIntToScalar(x),
1098 GrIntToScalar(y),
1099 GrIntToScalar(w),
1100 GrIntToScalar(h)),
1101 GrRect::MakeWH(GR_Scalar1, GR_Scalar1));
reed@google.comac10a2d2010-12-22 21:39:39 +00001102}
1103
1104///////////////////////////////////////////////////////////////////////////////
1105
1106// must be in SkCanvas::VertexMode order
bsalomon@google.comffca4002011-02-22 20:34:01 +00001107static const GrPrimitiveType gVertexMode2PrimitiveType[] = {
1108 kTriangles_PrimitiveType,
1109 kTriangleStrip_PrimitiveType,
1110 kTriangleFan_PrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +00001111};
1112
1113void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
1114 int vertexCount, const SkPoint vertices[],
1115 const SkPoint texs[], const SkColor colors[],
1116 SkXfermode* xmode,
1117 const uint16_t indices[], int indexCount,
1118 const SkPaint& paint) {
1119 CHECK_SHOULD_DRAW(draw);
1120
bsalomon@google.com5782d712011-01-21 21:03:59 +00001121 GrPaint grPaint;
1122 SkAutoCachedTexture act;
1123 // we ignore the shader if texs is null.
1124 if (NULL == texs) {
Scroggod757df22011-05-16 13:11:16 +00001125 if (!this->skPaint2GrPaintNoShader(paint,
1126 false,
1127 &grPaint,
1128 NULL == colors)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001129 return;
1130 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001131 } else {
reed@google.com1a2e8d22011-01-21 22:08:29 +00001132 if (!this->skPaint2GrPaintShader(paint, &act,
1133 *draw.fMatrix,
Scroggod757df22011-05-16 13:11:16 +00001134 &grPaint,
1135 NULL == colors)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001136 return;
1137 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001138 }
bsalomon@google.com5782d712011-01-21 21:03:59 +00001139
1140 if (NULL != xmode && NULL != texs && NULL != colors) {
1141 SkXfermode::Mode mode;
1142 if (!SkXfermode::IsMode(xmode, &mode) ||
1143 SkXfermode::kMultiply_Mode != mode) {
1144 SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
1145#if 0
1146 return
1147#endif
1148 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001149 }
bsalomon@google.com5782d712011-01-21 21:03:59 +00001150
1151#if SK_SCALAR_IS_GR_SCALAR
1152 // even if GrColor and SkColor byte offsets match we need
1153 // to perform pre-multiply.
1154 if (NULL == colors) {
1155 fContext->drawVertices(grPaint,
1156 gVertexMode2PrimitiveType[vmode],
1157 vertexCount,
1158 (GrPoint*) vertices,
1159 (GrPoint*) texs,
1160 NULL,
1161 indices,
1162 indexCount);
1163 } else
1164#endif
1165 {
1166 SkTexCoordSource texSrc(texs);
1167 SkColorSource colSrc(colors);
1168 SkIndexSource idxSrc(indices, indexCount);
1169
1170 fContext->drawCustomVertices(grPaint,
1171 gVertexMode2PrimitiveType[vmode],
1172 SkPositionSource(vertices, vertexCount),
1173 (NULL == texs) ? NULL : &texSrc,
1174 (NULL == colors) ? NULL : &colSrc,
1175 (NULL == indices) ? NULL : &idxSrc);
reed@google.comac10a2d2010-12-22 21:39:39 +00001176 }
1177}
1178
1179///////////////////////////////////////////////////////////////////////////////
1180
1181static void GlyphCacheAuxProc(void* data) {
1182 delete (GrFontScaler*)data;
1183}
1184
1185static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
1186 void* auxData;
1187 GrFontScaler* scaler = NULL;
1188 if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
1189 scaler = (GrFontScaler*)auxData;
1190 }
1191 if (NULL == scaler) {
1192 scaler = new SkGrFontScaler(cache);
1193 cache->setAuxProc(GlyphCacheAuxProc, scaler);
1194 }
1195 return scaler;
1196}
1197
1198static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
1199 SkFixed fx, SkFixed fy,
1200 const SkGlyph& glyph) {
1201 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1202
1203 GrSkDrawProcs* procs = (GrSkDrawProcs*)state.fDraw->fProcs;
1204
1205 if (NULL == procs->fFontScaler) {
1206 procs->fFontScaler = get_gr_font_scaler(state.fCache);
1207 }
reed@google.com39ce0ac2011-04-08 15:42:19 +00001208
1209 /*
1210 * Skia calls us with fx,fy already biased by 1/2. It does this to speed
1211 * up rounding these, so that all of its procs (like us) can just call
1212 * SkFixedFloor and get the "rounded" value.
1213 *
1214 * We take advantage of that for fx, where we pass a rounded value, but
1215 * we want the fractional fy, so we have to unbias it first.
1216 */
reed@google.comac10a2d2010-12-22 21:39:39 +00001217 procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), fx, 0),
reed@google.com39ce0ac2011-04-08 15:42:19 +00001218 SkIntToFixed(SkFixedFloor(fx)),
1219 fy - SK_FixedHalf,
reed@google.comac10a2d2010-12-22 21:39:39 +00001220 procs->fFontScaler);
1221}
1222
bsalomon@google.com5782d712011-01-21 21:03:59 +00001223SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001224
1225 // deferred allocation
1226 if (NULL == fDrawProcs) {
1227 fDrawProcs = new GrSkDrawProcs;
1228 fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
1229 fDrawProcs->fContext = fContext;
1230 }
1231
1232 // init our (and GL's) state
1233 fDrawProcs->fTextContext = context;
1234 fDrawProcs->fFontScaler = NULL;
1235 return fDrawProcs;
1236}
1237
1238void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
1239 size_t byteLength, SkScalar x, SkScalar y,
1240 const SkPaint& paint) {
1241 CHECK_SHOULD_DRAW(draw);
1242
1243 if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1244 // this guy will just call our drawPath()
1245 draw.drawText((const char*)text, byteLength, x, y, paint);
1246 } else {
reed@google.comac10a2d2010-12-22 21:39:39 +00001247 SkDraw myDraw(draw);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001248
1249 GrPaint grPaint;
1250 SkAutoCachedTexture act;
1251
Scroggod757df22011-05-16 13:11:16 +00001252 if (!this->skPaint2GrPaintShader(paint,
1253 &act,
1254 *draw.fMatrix,
1255 &grPaint,
1256 true)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001257 return;
1258 }
bsalomon@google.comcc4dac32011-05-10 13:52:42 +00001259 GrTextContext context(fContext, grPaint, draw.fExtMatrix);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001260 myDraw.fProcs = this->initDrawForText(&context);
reed@google.comac10a2d2010-12-22 21:39:39 +00001261 this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
1262 }
1263}
1264
1265void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
1266 size_t byteLength, const SkScalar pos[],
1267 SkScalar constY, int scalarsPerPos,
1268 const SkPaint& paint) {
1269 CHECK_SHOULD_DRAW(draw);
1270
1271 if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1272 // this guy will just call our drawPath()
1273 draw.drawPosText((const char*)text, byteLength, pos, constY,
1274 scalarsPerPos, paint);
1275 } else {
reed@google.comac10a2d2010-12-22 21:39:39 +00001276 SkDraw myDraw(draw);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001277
1278 GrPaint grPaint;
1279 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +00001280 if (!this->skPaint2GrPaintShader(paint,
1281 &act,
1282 *draw.fMatrix,
1283 &grPaint,
1284 true)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001285 return;
1286 }
1287
bsalomon@google.comcc4dac32011-05-10 13:52:42 +00001288 GrTextContext context(fContext, grPaint, draw.fExtMatrix);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001289 myDraw.fProcs = this->initDrawForText(&context);
reed@google.comac10a2d2010-12-22 21:39:39 +00001290 this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
1291 scalarsPerPos, paint);
1292 }
1293}
1294
1295void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
1296 size_t len, const SkPath& path,
1297 const SkMatrix* m, const SkPaint& paint) {
1298 CHECK_SHOULD_DRAW(draw);
1299
1300 SkASSERT(draw.fDevice == this);
1301 draw.drawTextOnPath((const char*)text, len, path, m, paint);
1302}
1303
1304///////////////////////////////////////////////////////////////////////////////
1305
reed@google.comf67e4cf2011-03-15 20:56:58 +00001306bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
1307 if (!paint.isLCDRenderText()) {
1308 // we're cool with the paint as is
1309 return false;
1310 }
1311
1312 if (paint.getShader() ||
1313 paint.getXfermode() || // unless its srcover
1314 paint.getMaskFilter() ||
1315 paint.getRasterizer() ||
1316 paint.getColorFilter() ||
1317 paint.getPathEffect() ||
1318 paint.isFakeBoldText() ||
1319 paint.getStyle() != SkPaint::kFill_Style) {
1320 // turn off lcd
1321 flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
1322 flags->fHinting = paint.getHinting();
1323 return true;
1324 }
1325 // we're cool with the paint as is
1326 return false;
1327}
1328
1329///////////////////////////////////////////////////////////////////////////////
1330
reed@google.comac10a2d2010-12-22 21:39:39 +00001331SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001332 const GrSamplerState& sampler,
1333 GrTexture** texture,
1334 bool forDeviceRenderTarget) {
1335 GrTexture* newTexture = NULL;
1336 GrTextureEntry* entry = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001337 GrContext* ctx = this->context();
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001338
reed@google.comac10a2d2010-12-22 21:39:39 +00001339 if (forDeviceRenderTarget) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001340 const GrTextureDesc desc = {
1341 kRenderTarget_GrTextureFlagBit,
1342 kNone_GrAALevel,
1343 bitmap.width(),
1344 bitmap.height(),
1345 SkGr::Bitmap2PixelConfig(bitmap)
1346 };
bsalomon@google.coma39f4042011-04-26 13:18:16 +00001347 entry = ctx->lockKeylessTexture(desc);
reed@google.comac10a2d2010-12-22 21:39:39 +00001348 } else {
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001349 uint32_t p0, p1;
reed@google.comac10a2d2010-12-22 21:39:39 +00001350 p0 = bitmap.getGenerationID();
1351 p1 = bitmap.pixelRefOffset();
reed@google.comac10a2d2010-12-22 21:39:39 +00001352
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001353 GrTextureKey key(p0, p1, bitmap.width(), bitmap.height());
1354 entry = ctx->findAndLockTexture(&key, sampler);
reed@google.comac10a2d2010-12-22 21:39:39 +00001355
reed@google.comac10a2d2010-12-22 21:39:39 +00001356 if (NULL == entry) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001357 entry = sk_gr_create_bitmap_texture(ctx, &key, sampler, bitmap);
1358 if (NULL == entry) {
1359 GrPrintf("---- failed to create texture for cache [%d %d]\n",
1360 bitmap.width(), bitmap.height());
1361 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001362 }
1363 }
1364
1365 if (NULL != entry) {
1366 newTexture = entry->texture();
reed@google.comac10a2d2010-12-22 21:39:39 +00001367 if (texture) {
1368 *texture = newTexture;
1369 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001370 }
1371 return (TexCache*)entry;
1372}
1373
1374void SkGpuDevice::unlockCachedTexture(TexCache* cache) {
1375 this->context()->unlockTexture((GrTextureEntry*)cache);
1376}
1377
reed@google.com7b201d22011-01-11 18:59:23 +00001378///////////////////////////////////////////////////////////////////////////////
1379
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001380SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context,
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001381 GrRenderTarget* rootRenderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001382 GrAssert(NULL != context);
1383 GrAssert(NULL != rootRenderTarget);
1384
1385 // check this now rather than passing this value to SkGpuDevice cons.
1386 // we want the rt that is bound *now* in the 3D API, not the one
1387 // at the time of newDevice.
1388 if (SkGpuDevice::Current3DApiRenderTarget() == rootRenderTarget) {
1389 fRootRenderTarget = context->createRenderTargetFrom3DApiState();
1390 } else {
1391 fRootRenderTarget = rootRenderTarget;
1392 rootRenderTarget->ref();
1393 }
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001394
1395 fContext = context;
reed@google.com7b201d22011-01-11 18:59:23 +00001396 context->ref();
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001397
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001398 fRootTexture = NULL;
1399}
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001400
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001401SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, GrTexture* rootRenderTargetTexture) {
1402 GrAssert(NULL != context);
1403 GrAssert(NULL != rootRenderTargetTexture);
1404 GrAssert(NULL != rootRenderTargetTexture->asRenderTarget());
1405
1406 fRootTexture = rootRenderTargetTexture;
1407 rootRenderTargetTexture->ref();
1408
1409 fRootRenderTarget = rootRenderTargetTexture->asRenderTarget();
1410 fRootRenderTarget->ref();
1411
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001412 fContext = context;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001413 context->ref();
reed@google.com7b201d22011-01-11 18:59:23 +00001414}
1415
1416SkGpuDeviceFactory::~SkGpuDeviceFactory() {
1417 fContext->unref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001418 fRootRenderTarget->unref();
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001419 GrSafeUnref(fRootTexture);
reed@google.com7b201d22011-01-11 18:59:23 +00001420}
1421
1422SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
1423 int width, int height,
1424 bool isOpaque, bool isLayer) {
1425 SkBitmap bm;
1426 bm.setConfig(config, width, height);
1427 bm.setIsOpaque(isOpaque);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001428 return new SkGpuDevice(fContext, bm, isLayer ? NULL : fRootRenderTarget);
reed@google.com7b201d22011-01-11 18:59:23 +00001429}