blob: d1cb5b9a101cc1135fb5880f7754874bb1678606 [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 }
reed@google.com67db6642011-05-26 11:46:35 +0000696 // until we aa rotated rects...
697 if (!usePath && paint.isAntiAlias() && !draw.fMatrix->rectStaysRect()) {
698 usePath = true;
699 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000700
701 if (usePath) {
702 SkPath path;
703 path.addRect(rect);
704 this->drawPath(draw, path, paint, NULL, true);
705 return;
706 }
707
708 GrPaint grPaint;
709 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +0000710 if (!this->skPaint2GrPaintShader(paint,
711 &act,
712 *draw.fMatrix,
713 &grPaint,
714 true)) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000715 return;
716 }
reed@google.com20efde72011-05-09 17:00:02 +0000717 fContext->drawRect(grPaint, rect, doStroke ? width : -1);
reed@google.comac10a2d2010-12-22 21:39:39 +0000718}
719
reed@google.com69302852011-02-16 18:08:07 +0000720#include "SkMaskFilter.h"
721#include "SkBounder.h"
722
reed@google.com69302852011-02-16 18:08:07 +0000723static bool drawWithMaskFilter(GrContext* context, const SkPath& path,
724 SkMaskFilter* filter, const SkMatrix& matrix,
725 const SkRegion& clip, SkBounder* bounder,
726 GrPaint* grp) {
727 SkMask srcM, dstM;
728
729 if (!SkDraw::DrawToMask(path, &clip.getBounds(), filter, &matrix, &srcM,
730 SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
731 return false;
732 }
733
734 SkAutoMaskImage autoSrc(&srcM, false);
735
736 if (!filter->filterMask(&dstM, srcM, matrix, NULL)) {
737 return false;
738 }
739 // this will free-up dstM when we're done (allocated in filterMask())
740 SkAutoMaskImage autoDst(&dstM, false);
741
742 if (clip.quickReject(dstM.fBounds)) {
743 return false;
744 }
745 if (bounder && !bounder->doIRect(dstM.fBounds)) {
746 return false;
747 }
748
749 // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
750 // the current clip (and identity matrix) and grpaint settings
751
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000752 // used to compute inverse view, if necessary
753 GrMatrix ivm = context->getMatrix();
754
reed@google.com0c219b62011-02-16 21:31:18 +0000755 GrAutoMatrix avm(context, GrMatrix::I());
reed@google.com69302852011-02-16 18:08:07 +0000756
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000757 const GrTextureDesc desc = {
758 kNone_GrTextureFlags,
759 kNone_GrAALevel,
reed@google.com69302852011-02-16 18:08:07 +0000760 dstM.fBounds.width(),
761 dstM.fBounds.height(),
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000762 kAlpha_8_GrPixelConfig
reed@google.com69302852011-02-16 18:08:07 +0000763 };
764
765 GrTexture* texture = context->createUncachedTexture(desc, dstM.fImage,
766 dstM.fRowBytes);
767 if (NULL == texture) {
768 return false;
769 }
770
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000771 if (grp->hasTextureOrMask() && ivm.invert(&ivm)) {
772 grp->preConcatActiveSamplerMatrices(ivm);
773 }
774
775 static const int MASK_IDX = GrPaint::kMaxMasks - 1;
776 // we assume the last mask index is available for use
777 GrAssert(NULL == grp->getMask(MASK_IDX));
778 grp->setMask(MASK_IDX, texture);
reed@google.com0c219b62011-02-16 21:31:18 +0000779 texture->unref();
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000780 grp->getMaskSampler(MASK_IDX)->setClampNoFilter();
reed@google.com69302852011-02-16 18:08:07 +0000781
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000782 GrRect d;
783 d.setLTRB(GrIntToScalar(dstM.fBounds.fLeft),
reed@google.com0c219b62011-02-16 21:31:18 +0000784 GrIntToScalar(dstM.fBounds.fTop),
785 GrIntToScalar(dstM.fBounds.fRight),
786 GrIntToScalar(dstM.fBounds.fBottom));
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000787
788 GrMatrix m;
789 m.setTranslate(-dstM.fBounds.fLeft, -dstM.fBounds.fTop);
790 m.postIDiv(dstM.fBounds.width(), dstM.fBounds.height());
791 grp->getMaskSampler(MASK_IDX)->setMatrix(m);
792
793 context->drawRect(*grp, d);
reed@google.com69302852011-02-16 18:08:07 +0000794 return true;
795}
reed@google.com69302852011-02-16 18:08:07 +0000796
reed@google.com0c219b62011-02-16 21:31:18 +0000797void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
reed@google.comac10a2d2010-12-22 21:39:39 +0000798 const SkPaint& paint, const SkMatrix* prePathMatrix,
799 bool pathIsMutable) {
800 CHECK_SHOULD_DRAW(draw);
801
bsalomon@google.com5782d712011-01-21 21:03:59 +0000802 GrPaint grPaint;
803 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +0000804 if (!this->skPaint2GrPaintShader(paint,
805 &act,
806 *draw.fMatrix,
807 &grPaint,
808 true)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000809 return;
810 }
811
reed@google.com0c219b62011-02-16 21:31:18 +0000812 // BEGIN lift from SkDraw::drawPath()
813
814 SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
815 bool doFill = true;
816 SkPath tmpPath;
reed@google.comac10a2d2010-12-22 21:39:39 +0000817
818 if (prePathMatrix) {
reed@google.come3445642011-02-16 23:20:39 +0000819 SkPath* result = pathPtr;
reed@google.com0c219b62011-02-16 21:31:18 +0000820
reed@google.come3445642011-02-16 23:20:39 +0000821 if (!pathIsMutable) {
822 result = &tmpPath;
823 pathIsMutable = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000824 }
reed@google.come3445642011-02-16 23:20:39 +0000825 // should I push prePathMatrix on our MV stack temporarily, instead
826 // of applying it here? See SkDraw.cpp
827 pathPtr->transform(*prePathMatrix, result);
828 pathPtr = result;
reed@google.comac10a2d2010-12-22 21:39:39 +0000829 }
reed@google.com0c219b62011-02-16 21:31:18 +0000830 // at this point we're done with prePathMatrix
831 SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
reed@google.comac10a2d2010-12-22 21:39:39 +0000832
bsalomon@google.com04de7822011-03-25 18:04:43 +0000833 // This "if" is not part of the SkDraw::drawPath() lift.
834 // When we get a 1.0 wide stroke we hairline stroke it instead of creating
835 // a new stroked-path. This is motivated by canvas2D sites that draw
836 // lines as 1.0 wide stroked paths. We can consider doing an alpha-modulated-
837 // hairline for width < 1.0 when AA is enabled.
838 static const int gMatrixMask = ~(SkMatrix::kIdentity_Mask |
839 SkMatrix::kTranslate_Mask);
840 if (!paint.getPathEffect() &&
841 SkPaint::kStroke_Style == paint.getStyle() &&
842 !(draw.fMatrix->getType() & gMatrixMask) &&
843 SK_Scalar1 == paint.getStrokeWidth()) {
844 doFill = false;
845 }
846
847 if (doFill && (paint.getPathEffect() ||
848 paint.getStyle() != SkPaint::kFill_Style)) {
reed@google.com0c219b62011-02-16 21:31:18 +0000849 doFill = paint.getFillPath(*pathPtr, &tmpPath);
850 pathPtr = &tmpPath;
851 }
852
853 // END lift from SkDraw::drawPath()
854
reed@google.com69302852011-02-16 18:08:07 +0000855 if (paint.getMaskFilter()) {
reed@google.com0c219b62011-02-16 21:31:18 +0000856 // avoid possibly allocating a new path in transform if we can
857 SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
858
859 // transform the path into device space
reed@google.come3445642011-02-16 23:20:39 +0000860 pathPtr->transform(*draw.fMatrix, devPathPtr);
reed@google.com0c219b62011-02-16 21:31:18 +0000861
862 drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
reed@google.com69302852011-02-16 18:08:07 +0000863 *draw.fMatrix, *draw.fClip, draw.fBounder, &grPaint);
864 return;
865 }
reed@google.com69302852011-02-16 18:08:07 +0000866
bsalomon@google.comffca4002011-02-22 20:34:01 +0000867 GrPathFill fill = kHairLine_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000868
reed@google.com0c219b62011-02-16 21:31:18 +0000869 if (doFill) {
870 switch (pathPtr->getFillType()) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000871 case SkPath::kWinding_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000872 fill = kWinding_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000873 break;
874 case SkPath::kEvenOdd_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000875 fill = kEvenOdd_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000876 break;
877 case SkPath::kInverseWinding_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000878 fill = kInverseWinding_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000879 break;
880 case SkPath::kInverseEvenOdd_FillType:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000881 fill = kInverseEvenOdd_PathFill;
reed@google.comac10a2d2010-12-22 21:39:39 +0000882 break;
883 default:
bsalomon@google.com5782d712011-01-21 21:03:59 +0000884 SkDebugf("Unsupported path fill type\n");
reed@google.comac10a2d2010-12-22 21:39:39 +0000885 return;
886 }
887 }
888
reed@google.com07f3ee12011-05-16 17:21:57 +0000889 fContext->drawPath(grPaint, *pathPtr, fill);
reed@google.comac10a2d2010-12-22 21:39:39 +0000890}
891
reed@google.comac10a2d2010-12-22 21:39:39 +0000892void SkGpuDevice::drawBitmap(const SkDraw& draw,
893 const SkBitmap& bitmap,
894 const SkIRect* srcRectPtr,
895 const SkMatrix& m,
896 const SkPaint& paint) {
897 CHECK_SHOULD_DRAW(draw);
898
899 SkIRect srcRect;
900 if (NULL == srcRectPtr) {
901 srcRect.set(0, 0, bitmap.width(), bitmap.height());
902 } else {
903 srcRect = *srcRectPtr;
904 }
905
bsalomon@google.com5782d712011-01-21 21:03:59 +0000906 GrPaint grPaint;
Scroggod757df22011-05-16 13:11:16 +0000907 if (!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000908 return;
909 }
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000910 GrSamplerState* sampler = grPaint.getTextureSampler(kBitmapTextureIdx);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000911 if (paint.isFilterBitmap()) {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000912 sampler->setFilter(GrSamplerState::kBilinear_Filter);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000913 } else {
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000914 sampler->setFilter(GrSamplerState::kNearest_Filter);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000915 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000916
bsalomon@google.com91958362011-06-13 17:58:13 +0000917 const int maxTextureSize = fContext->getMaxTextureSize();
918 if (bitmap.getTexture() || (bitmap.width() <= maxTextureSize &&
919 bitmap.height() <= maxTextureSize)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000920 // take the fast case
bsalomon@google.com5782d712011-01-21 21:03:59 +0000921 this->internalDrawBitmap(draw, bitmap, srcRect, m, &grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000922 return;
923 }
924
925 // undo the translate done by SkCanvas
926 int DX = SkMax32(0, srcRect.fLeft);
927 int DY = SkMax32(0, srcRect.fTop);
928 // compute clip bounds in local coordinates
929 SkIRect clipRect;
930 {
931 SkRect r;
932 r.set(draw.fClip->getBounds());
933 SkMatrix matrix, inverse;
934 matrix.setConcat(*draw.fMatrix, m);
935 if (!matrix.invert(&inverse)) {
936 return;
937 }
938 inverse.mapRect(&r);
939 r.roundOut(&clipRect);
940 // apply the canvas' translate to our local clip
941 clipRect.offset(DX, DY);
942 }
943
bsalomon@google.com91958362011-06-13 17:58:13 +0000944 int nx = bitmap.width() / maxTextureSize;
945 int ny = bitmap.height() / maxTextureSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000946 for (int x = 0; x <= nx; x++) {
947 for (int y = 0; y <= ny; y++) {
948 SkIRect tileR;
bsalomon@google.com91958362011-06-13 17:58:13 +0000949 tileR.set(x * maxTextureSize, y * maxTextureSize,
950 (x + 1) * maxTextureSize, (y + 1) * maxTextureSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000951 if (!SkIRect::Intersects(tileR, clipRect)) {
952 continue;
953 }
954
955 SkIRect srcR = tileR;
956 if (!srcR.intersect(srcRect)) {
957 continue;
958 }
959
960 SkBitmap tmpB;
961 if (bitmap.extractSubset(&tmpB, tileR)) {
962 // now offset it to make it "local" to our tmp bitmap
963 srcR.offset(-tileR.fLeft, -tileR.fTop);
964
965 SkMatrix tmpM(m);
966 {
967 int dx = tileR.fLeft - DX + SkMax32(0, srcR.fLeft);
968 int dy = tileR.fTop - DY + SkMax32(0, srcR.fTop);
969 tmpM.preTranslate(SkIntToScalar(dx), SkIntToScalar(dy));
970 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000971 this->internalDrawBitmap(draw, tmpB, srcR, tmpM, &grPaint);
reed@google.comac10a2d2010-12-22 21:39:39 +0000972 }
973 }
974 }
975}
976
977/*
978 * This is called by drawBitmap(), which has to handle images that may be too
979 * large to be represented by a single texture.
980 *
bsalomon@google.com5782d712011-01-21 21:03:59 +0000981 * internalDrawBitmap assumes that the specified bitmap will fit in a texture
982 * and that non-texture portion of the GrPaint has already been setup.
reed@google.comac10a2d2010-12-22 21:39:39 +0000983 */
984void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
985 const SkBitmap& bitmap,
986 const SkIRect& srcRect,
987 const SkMatrix& m,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000988 GrPaint* grPaint) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000989 SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() &&
990 bitmap.height() <= fContext->getMaxTextureSize());
reed@google.comac10a2d2010-12-22 21:39:39 +0000991
992 SkAutoLockPixels alp(bitmap);
993 if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
994 return;
995 }
996
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +0000997 GrSamplerState* sampler = grPaint->getTextureSampler(kBitmapTextureIdx);
998
999 sampler->setWrapX(GrSamplerState::kClamp_WrapMode);
1000 sampler->setWrapY(GrSamplerState::kClamp_WrapMode);
1001 sampler->setSampleMode(GrSamplerState::kNormal_SampleMode);
1002 sampler->setMatrix(GrMatrix::I());
reed@google.comac10a2d2010-12-22 21:39:39 +00001003
1004 GrTexture* texture;
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001005 SkAutoCachedTexture act(this, bitmap, *sampler, &texture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001006 if (NULL == texture) {
1007 return;
1008 }
1009
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001010 grPaint->setTexture(kShaderTextureIdx, texture);
reed@google.com46799cd2011-02-22 20:56:26 +00001011
reed@google.com20efde72011-05-09 17:00:02 +00001012 GrRect dstRect = SkRect::MakeWH(GrIntToScalar(srcRect.width()),
1013 GrIntToScalar(srcRect.height()));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001014 GrRect paintRect;
junov@google.com6acc9b32011-05-16 18:32:07 +00001015 paintRect.setLTRB(GrFixedToScalar((srcRect.fLeft << 16) / bitmap.width()),
1016 GrFixedToScalar((srcRect.fTop << 16) / bitmap.height()),
1017 GrFixedToScalar((srcRect.fRight << 16) / bitmap.width()),
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001018 GrFixedToScalar((srcRect.fBottom << 16) / bitmap.height()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001019
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001020 if (GrSamplerState::kNearest_Filter != sampler->getFilter() &&
junov@google.com6acc9b32011-05-16 18:32:07 +00001021 (srcRect.width() < bitmap.width() ||
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001022 srcRect.height() < bitmap.height())) {
junov@google.com6acc9b32011-05-16 18:32:07 +00001023 // If drawing a subrect of the bitmap and filtering is enabled,
1024 // use a constrained texture domain to avoid color bleeding
1025 GrScalar left, top, right, bottom;
1026 if (srcRect.width() > 1) {
1027 GrScalar border = GR_ScalarHalf / bitmap.width();
1028 left = paintRect.left() + border;
1029 right = paintRect.right() - border;
1030 } else {
1031 left = right = GrScalarHalf(paintRect.left() + paintRect.right());
1032 }
1033 if (srcRect.height() > 1) {
1034 GrScalar border = GR_ScalarHalf / bitmap.height();
1035 top = paintRect.top() + border;
1036 bottom = paintRect.bottom() - border;
1037 } else {
1038 top = bottom = GrScalarHalf(paintRect.top() + paintRect.bottom());
1039 }
1040 GrRect textureDomain;
1041 textureDomain.setLTRB(left, top, right, bottom);
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001042 sampler->setTextureDomain(textureDomain);
junov@google.com6acc9b32011-05-16 18:32:07 +00001043 }
1044
bsalomon@google.comcc4dac32011-05-10 13:52:42 +00001045 fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m);
reed@google.comac10a2d2010-12-22 21:39:39 +00001046}
1047
1048void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
1049 int left, int top, const SkPaint& paint) {
1050 CHECK_SHOULD_DRAW(draw);
1051
1052 SkAutoLockPixels alp(bitmap);
1053 if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
1054 return;
1055 }
1056
bsalomon@google.com5782d712011-01-21 21:03:59 +00001057 GrPaint grPaint;
Scroggod757df22011-05-16 13:11:16 +00001058 if(!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001059 return;
1060 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001061
bsalomon@google.com5782d712011-01-21 21:03:59 +00001062 GrAutoMatrix avm(fContext, GrMatrix::I());
1063
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001064 GrSamplerState* sampler = grPaint.getTextureSampler(kBitmapTextureIdx);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001065
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001066 GrTexture* texture;
1067 sampler->setClampNoFilter();
1068 SkAutoCachedTexture act(this, bitmap, *sampler, &texture);
1069
1070 grPaint.setTexture(kBitmapTextureIdx, texture);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001071
bsalomon@google.com5782d712011-01-21 21:03:59 +00001072 fContext->drawRectToRect(grPaint,
reed@google.com20efde72011-05-09 17:00:02 +00001073 GrRect::MakeXYWH(GrIntToScalar(left),
1074 GrIntToScalar(top),
1075 GrIntToScalar(bitmap.width()),
1076 GrIntToScalar(bitmap.height())),
1077 GrRect::MakeWH(GR_Scalar1, GR_Scalar1));
reed@google.comac10a2d2010-12-22 21:39:39 +00001078}
1079
1080void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* dev,
1081 int x, int y, const SkPaint& paint) {
1082 CHECK_SHOULD_DRAW(draw);
1083
bsalomon@google.com5782d712011-01-21 21:03:59 +00001084 GrPaint grPaint;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001085 if (!((SkGpuDevice*)dev)->bindDeviceAsTexture(&grPaint) ||
Scroggod757df22011-05-16 13:11:16 +00001086 !this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001087 return;
reed@google.comac10a2d2010-12-22 21:39:39 +00001088 }
bsalomon@google.com5782d712011-01-21 21:03:59 +00001089
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001090 SkASSERT(NULL != grPaint.getTexture(0));
bsalomon@google.com5782d712011-01-21 21:03:59 +00001091
1092 const SkBitmap& bm = dev->accessBitmap(false);
1093 int w = bm.width();
1094 int h = bm.height();
1095
1096 GrAutoMatrix avm(fContext, GrMatrix::I());
1097
bsalomon@google.com26c2d0a2011-05-17 20:15:30 +00001098 grPaint.getTextureSampler(kBitmapTextureIdx)->setClampNoFilter();
bsalomon@google.com5782d712011-01-21 21:03:59 +00001099
1100 fContext->drawRectToRect(grPaint,
reed@google.com20efde72011-05-09 17:00:02 +00001101 GrRect::MakeXYWH(GrIntToScalar(x),
1102 GrIntToScalar(y),
1103 GrIntToScalar(w),
1104 GrIntToScalar(h)),
1105 GrRect::MakeWH(GR_Scalar1, GR_Scalar1));
reed@google.comac10a2d2010-12-22 21:39:39 +00001106}
1107
1108///////////////////////////////////////////////////////////////////////////////
1109
1110// must be in SkCanvas::VertexMode order
bsalomon@google.comffca4002011-02-22 20:34:01 +00001111static const GrPrimitiveType gVertexMode2PrimitiveType[] = {
1112 kTriangles_PrimitiveType,
1113 kTriangleStrip_PrimitiveType,
1114 kTriangleFan_PrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +00001115};
1116
1117void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
1118 int vertexCount, const SkPoint vertices[],
1119 const SkPoint texs[], const SkColor colors[],
1120 SkXfermode* xmode,
1121 const uint16_t indices[], int indexCount,
1122 const SkPaint& paint) {
1123 CHECK_SHOULD_DRAW(draw);
1124
bsalomon@google.com5782d712011-01-21 21:03:59 +00001125 GrPaint grPaint;
1126 SkAutoCachedTexture act;
1127 // we ignore the shader if texs is null.
1128 if (NULL == texs) {
Scroggod757df22011-05-16 13:11:16 +00001129 if (!this->skPaint2GrPaintNoShader(paint,
1130 false,
1131 &grPaint,
1132 NULL == colors)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001133 return;
1134 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001135 } else {
reed@google.com1a2e8d22011-01-21 22:08:29 +00001136 if (!this->skPaint2GrPaintShader(paint, &act,
1137 *draw.fMatrix,
Scroggod757df22011-05-16 13:11:16 +00001138 &grPaint,
1139 NULL == colors)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001140 return;
1141 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001142 }
bsalomon@google.com5782d712011-01-21 21:03:59 +00001143
1144 if (NULL != xmode && NULL != texs && NULL != colors) {
1145 SkXfermode::Mode mode;
1146 if (!SkXfermode::IsMode(xmode, &mode) ||
1147 SkXfermode::kMultiply_Mode != mode) {
1148 SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
1149#if 0
1150 return
1151#endif
1152 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001153 }
bsalomon@google.com5782d712011-01-21 21:03:59 +00001154
1155#if SK_SCALAR_IS_GR_SCALAR
1156 // even if GrColor and SkColor byte offsets match we need
1157 // to perform pre-multiply.
1158 if (NULL == colors) {
1159 fContext->drawVertices(grPaint,
1160 gVertexMode2PrimitiveType[vmode],
1161 vertexCount,
1162 (GrPoint*) vertices,
1163 (GrPoint*) texs,
1164 NULL,
1165 indices,
1166 indexCount);
1167 } else
1168#endif
1169 {
1170 SkTexCoordSource texSrc(texs);
1171 SkColorSource colSrc(colors);
1172 SkIndexSource idxSrc(indices, indexCount);
1173
1174 fContext->drawCustomVertices(grPaint,
1175 gVertexMode2PrimitiveType[vmode],
1176 SkPositionSource(vertices, vertexCount),
1177 (NULL == texs) ? NULL : &texSrc,
1178 (NULL == colors) ? NULL : &colSrc,
1179 (NULL == indices) ? NULL : &idxSrc);
reed@google.comac10a2d2010-12-22 21:39:39 +00001180 }
1181}
1182
1183///////////////////////////////////////////////////////////////////////////////
1184
1185static void GlyphCacheAuxProc(void* data) {
1186 delete (GrFontScaler*)data;
1187}
1188
1189static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
1190 void* auxData;
1191 GrFontScaler* scaler = NULL;
1192 if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
1193 scaler = (GrFontScaler*)auxData;
1194 }
1195 if (NULL == scaler) {
1196 scaler = new SkGrFontScaler(cache);
1197 cache->setAuxProc(GlyphCacheAuxProc, scaler);
1198 }
1199 return scaler;
1200}
1201
1202static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
1203 SkFixed fx, SkFixed fy,
1204 const SkGlyph& glyph) {
1205 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1206
1207 GrSkDrawProcs* procs = (GrSkDrawProcs*)state.fDraw->fProcs;
1208
1209 if (NULL == procs->fFontScaler) {
1210 procs->fFontScaler = get_gr_font_scaler(state.fCache);
1211 }
reed@google.com39ce0ac2011-04-08 15:42:19 +00001212
1213 /*
reed@google.com3b139f52011-06-07 17:56:25 +00001214 * What should we do with fy? (assuming horizontal/latin text)
reed@google.com39ce0ac2011-04-08 15:42:19 +00001215 *
reed@google.com3b139f52011-06-07 17:56:25 +00001216 * The raster code calls SkFixedFloorToFixed on it, as it does with fx.
1217 * It calls that rather than round, because our caller has already added
1218 * SK_FixedHalf, so that calling floor gives us the rounded integer.
1219 *
1220 * Test code between raster and gpu (they should draw the same)
1221 *
1222 * canvas->drawText("Hamburgefons", 12, 0, 16.5f, paint);
1223 *
1224 * Perhaps we should only perform this integralization if there is no
1225 * fExtMatrix...
reed@google.com39ce0ac2011-04-08 15:42:19 +00001226 */
reed@google.com3b139f52011-06-07 17:56:25 +00001227 fy = SkFixedFloorToFixed(fy);
1228
reed@google.comac10a2d2010-12-22 21:39:39 +00001229 procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), fx, 0),
reed@google.com3b139f52011-06-07 17:56:25 +00001230 SkFixedFloorToFixed(fx), fy,
reed@google.comac10a2d2010-12-22 21:39:39 +00001231 procs->fFontScaler);
1232}
1233
bsalomon@google.com5782d712011-01-21 21:03:59 +00001234SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001235
1236 // deferred allocation
1237 if (NULL == fDrawProcs) {
1238 fDrawProcs = new GrSkDrawProcs;
1239 fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
1240 fDrawProcs->fContext = fContext;
1241 }
1242
1243 // init our (and GL's) state
1244 fDrawProcs->fTextContext = context;
1245 fDrawProcs->fFontScaler = NULL;
1246 return fDrawProcs;
1247}
1248
1249void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
1250 size_t byteLength, SkScalar x, SkScalar y,
1251 const SkPaint& paint) {
1252 CHECK_SHOULD_DRAW(draw);
1253
1254 if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1255 // this guy will just call our drawPath()
1256 draw.drawText((const char*)text, byteLength, x, y, paint);
1257 } else {
reed@google.comac10a2d2010-12-22 21:39:39 +00001258 SkDraw myDraw(draw);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001259
1260 GrPaint grPaint;
1261 SkAutoCachedTexture act;
1262
Scroggod757df22011-05-16 13:11:16 +00001263 if (!this->skPaint2GrPaintShader(paint,
1264 &act,
1265 *draw.fMatrix,
1266 &grPaint,
1267 true)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001268 return;
1269 }
bsalomon@google.comcc4dac32011-05-10 13:52:42 +00001270 GrTextContext context(fContext, grPaint, draw.fExtMatrix);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001271 myDraw.fProcs = this->initDrawForText(&context);
reed@google.comac10a2d2010-12-22 21:39:39 +00001272 this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
1273 }
1274}
1275
1276void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
1277 size_t byteLength, const SkScalar pos[],
1278 SkScalar constY, int scalarsPerPos,
1279 const SkPaint& paint) {
1280 CHECK_SHOULD_DRAW(draw);
1281
1282 if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1283 // this guy will just call our drawPath()
1284 draw.drawPosText((const char*)text, byteLength, pos, constY,
1285 scalarsPerPos, paint);
1286 } else {
reed@google.comac10a2d2010-12-22 21:39:39 +00001287 SkDraw myDraw(draw);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001288
1289 GrPaint grPaint;
1290 SkAutoCachedTexture act;
Scroggod757df22011-05-16 13:11:16 +00001291 if (!this->skPaint2GrPaintShader(paint,
1292 &act,
1293 *draw.fMatrix,
1294 &grPaint,
1295 true)) {
bsalomon@google.com5782d712011-01-21 21:03:59 +00001296 return;
1297 }
1298
bsalomon@google.comcc4dac32011-05-10 13:52:42 +00001299 GrTextContext context(fContext, grPaint, draw.fExtMatrix);
bsalomon@google.com5782d712011-01-21 21:03:59 +00001300 myDraw.fProcs = this->initDrawForText(&context);
reed@google.comac10a2d2010-12-22 21:39:39 +00001301 this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
1302 scalarsPerPos, paint);
1303 }
1304}
1305
1306void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
1307 size_t len, const SkPath& path,
1308 const SkMatrix* m, const SkPaint& paint) {
1309 CHECK_SHOULD_DRAW(draw);
1310
1311 SkASSERT(draw.fDevice == this);
1312 draw.drawTextOnPath((const char*)text, len, path, m, paint);
1313}
1314
1315///////////////////////////////////////////////////////////////////////////////
1316
reed@google.comf67e4cf2011-03-15 20:56:58 +00001317bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
1318 if (!paint.isLCDRenderText()) {
1319 // we're cool with the paint as is
1320 return false;
1321 }
1322
1323 if (paint.getShader() ||
1324 paint.getXfermode() || // unless its srcover
1325 paint.getMaskFilter() ||
1326 paint.getRasterizer() ||
1327 paint.getColorFilter() ||
1328 paint.getPathEffect() ||
1329 paint.isFakeBoldText() ||
1330 paint.getStyle() != SkPaint::kFill_Style) {
1331 // turn off lcd
1332 flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
1333 flags->fHinting = paint.getHinting();
1334 return true;
1335 }
1336 // we're cool with the paint as is
1337 return false;
1338}
1339
1340///////////////////////////////////////////////////////////////////////////////
1341
reed@google.comac10a2d2010-12-22 21:39:39 +00001342SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001343 const GrSamplerState& sampler,
1344 GrTexture** texture,
1345 bool forDeviceRenderTarget) {
1346 GrTexture* newTexture = NULL;
1347 GrTextureEntry* entry = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001348 GrContext* ctx = this->context();
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001349
reed@google.comac10a2d2010-12-22 21:39:39 +00001350 if (forDeviceRenderTarget) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001351 const GrTextureDesc desc = {
1352 kRenderTarget_GrTextureFlagBit,
1353 kNone_GrAALevel,
1354 bitmap.width(),
1355 bitmap.height(),
1356 SkGr::Bitmap2PixelConfig(bitmap)
1357 };
bsalomon@google.coma39f4042011-04-26 13:18:16 +00001358 entry = ctx->lockKeylessTexture(desc);
reed@google.comac10a2d2010-12-22 21:39:39 +00001359 } else {
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001360 uint32_t p0, p1;
reed@google.comac10a2d2010-12-22 21:39:39 +00001361 p0 = bitmap.getGenerationID();
1362 p1 = bitmap.pixelRefOffset();
reed@google.comac10a2d2010-12-22 21:39:39 +00001363
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001364 GrTextureKey key(p0, p1, bitmap.width(), bitmap.height());
1365 entry = ctx->findAndLockTexture(&key, sampler);
reed@google.comac10a2d2010-12-22 21:39:39 +00001366
reed@google.comac10a2d2010-12-22 21:39:39 +00001367 if (NULL == entry) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001368 entry = sk_gr_create_bitmap_texture(ctx, &key, sampler, bitmap);
1369 if (NULL == entry) {
1370 GrPrintf("---- failed to create texture for cache [%d %d]\n",
1371 bitmap.width(), bitmap.height());
1372 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001373 }
1374 }
1375
1376 if (NULL != entry) {
1377 newTexture = entry->texture();
reed@google.comac10a2d2010-12-22 21:39:39 +00001378 if (texture) {
1379 *texture = newTexture;
1380 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001381 }
1382 return (TexCache*)entry;
1383}
1384
1385void SkGpuDevice::unlockCachedTexture(TexCache* cache) {
1386 this->context()->unlockTexture((GrTextureEntry*)cache);
1387}
1388
reed@google.com7b201d22011-01-11 18:59:23 +00001389///////////////////////////////////////////////////////////////////////////////
1390
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001391SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context,
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001392 GrRenderTarget* rootRenderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001393 GrAssert(NULL != context);
1394 GrAssert(NULL != rootRenderTarget);
1395
1396 // check this now rather than passing this value to SkGpuDevice cons.
1397 // we want the rt that is bound *now* in the 3D API, not the one
1398 // at the time of newDevice.
1399 if (SkGpuDevice::Current3DApiRenderTarget() == rootRenderTarget) {
1400 fRootRenderTarget = context->createRenderTargetFrom3DApiState();
1401 } else {
1402 fRootRenderTarget = rootRenderTarget;
1403 rootRenderTarget->ref();
1404 }
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001405
1406 fContext = context;
reed@google.com7b201d22011-01-11 18:59:23 +00001407 context->ref();
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001408
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001409 fRootTexture = NULL;
1410}
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001411
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001412SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, GrTexture* rootRenderTargetTexture) {
1413 GrAssert(NULL != context);
1414 GrAssert(NULL != rootRenderTargetTexture);
1415 GrAssert(NULL != rootRenderTargetTexture->asRenderTarget());
1416
1417 fRootTexture = rootRenderTargetTexture;
1418 rootRenderTargetTexture->ref();
1419
1420 fRootRenderTarget = rootRenderTargetTexture->asRenderTarget();
1421 fRootRenderTarget->ref();
1422
bsalomon@google.comea2ee8a2011-04-12 17:58:39 +00001423 fContext = context;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001424 context->ref();
reed@google.com7b201d22011-01-11 18:59:23 +00001425}
1426
1427SkGpuDeviceFactory::~SkGpuDeviceFactory() {
1428 fContext->unref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001429 fRootRenderTarget->unref();
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001430 GrSafeUnref(fRootTexture);
reed@google.com7b201d22011-01-11 18:59:23 +00001431}
1432
1433SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
1434 int width, int height,
1435 bool isOpaque, bool isLayer) {
1436 SkBitmap bm;
1437 bm.setConfig(config, width, height);
1438 bm.setIsOpaque(isOpaque);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001439 return new SkGpuDevice(fContext, bm, isLayer ? NULL : fRootRenderTarget);
reed@google.com7b201d22011-01-11 18:59:23 +00001440}