1 /* 2 Copyright 2011 Google Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 18 #include "GrContext.h" 19 #include "GrTextContext.h" 20 21 #include "SkGpuDevice.h" 22 #include "SkGpuDeviceFactory.h" 23 #include "SkGrTexturePixelRef.h" 24 25 #include "SkColorFilter.h" 26 #include "SkDrawProcs.h" 27 #include "SkGlyphCache.h" 28 #include "SkUtils.h" 29 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 43 // we use the same texture slot on GrPaint for bitmaps and shaders 44 // (since drawBitmap, drawSprite, and drawDevice ignore skia's shader) 45 enum { 46 kBitmapTextureIdx = 0, 47 kShaderTextureIdx = 0 48 }; 49 50 /////////////////////////////////////////////////////////////////////////////// 51 52 SkGpuDevice::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 62 SkGpuDevice::SkAutoCachedTexture::SkAutoCachedTexture() { 63 fTex = NULL; 64 } 65 66 GrTexture* 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; 77 } else { 78 // look it up in our cache 79 fTex = device->lockCachedTexture(bitmap, sampler, &texture, false); 80 } 81 return texture; 82 } 83 84 SkGpuDevice::SkAutoCachedTexture::~SkAutoCachedTexture() { 85 if (fTex) { 86 fDevice->unlockCachedTexture(fTex); 87 } 88 } 89 90 /////////////////////////////////////////////////////////////////////////////// 91 92 bool gDoTraceDraw; 93 94 struct GrSkDrawProcs : public SkDrawProcs { 95 public: 96 GrContext* fContext; 97 GrTextContext* fTextContext; 98 GrFontScaler* fFontScaler; // cached in the skia glyphcache 99 }; 100 101 /////////////////////////////////////////////////////////////////////////////// 102 103 GrRenderTarget* SkGpuDevice::Current3DApiRenderTarget() { 104 return (GrRenderTarget*) -1; 105 } 106 107 SkGpuDevice::SkGpuDevice(GrContext* context, 108 const SkBitmap& bitmap, 109 GrRenderTarget* renderTargetOrNull) 110 : SkDevice(NULL, bitmap, (NULL == renderTargetOrNull)) { 111 112 fNeedPrepareRenderTarget = false; 113 fDrawProcs = NULL; 114 115 fContext = context; 116 fContext->ref(); 117 118 fCache = NULL; 119 fTexture = NULL; 120 fRenderTarget = NULL; 121 fNeedClear = false; 122 123 if (NULL == renderTargetOrNull) { 124 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); 137 SkASSERT(NULL != fTexture->asRenderTarget()); 138 } 139 #else 140 const GrTextureDesc desc = { 141 kRenderTarget_GrTextureFlagBit, 142 kNone_GrAALevel, 143 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()); 164 GrAssert(false); 165 } 166 } else { 167 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(); 175 } 176 } 177 178 SkGpuDevice::~SkGpuDevice() { 179 if (fDrawProcs) { 180 delete fDrawProcs; 181 } 182 183 if (fCache) { 184 GrAssert(NULL != fTexture); 185 GrAssert(fRenderTarget == fTexture->asRenderTarget()); 186 fContext->unlockTexture((GrTextureEntry*)fCache); 187 } 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 } 194 fContext->unref(); 195 } 196 197 intptr_t SkGpuDevice::getLayerTextureHandle() const { 198 if (fTexture) { 199 return fTexture->getTextureHandle(); 200 } else { 201 return 0; 202 } 203 } 204 205 SkDeviceFactory* SkGpuDevice::onNewDeviceFactory() { 206 return SkNEW_ARGS(SkGpuDeviceFactory, (fContext, fRenderTarget)); 207 } 208 209 /////////////////////////////////////////////////////////////////////////////// 210 211 void SkGpuDevice::makeRenderTargetCurrent() { 212 fContext->setRenderTarget(fRenderTarget); 213 fContext->flush(true); 214 fNeedPrepareRenderTarget = true; 215 } 216 217 /////////////////////////////////////////////////////////////////////////////// 218 219 bool SkGpuDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 220 SkIRect bounds; 221 bounds.set(0, 0, this->width(), this->height()); 222 if (!bounds.intersect(srcRect)) { 223 return false; 224 } 225 226 const int w = bounds.width(); 227 const int h = bounds.height(); 228 SkBitmap tmp; 229 // note we explicitly specify our rowBytes to be snug (no gap between rows) 230 tmp.setConfig(SkBitmap::kARGB_8888_Config, w, h, w * 4); 231 if (!tmp.allocPixels()) { 232 return false; 233 } 234 235 tmp.lockPixels(); 236 237 bool read = fContext->readRenderTargetPixels(fRenderTarget, 238 bounds.fLeft, bounds.fTop, 239 bounds.width(), bounds.height(), 240 kRGBA_8888_GrPixelConfig, 241 tmp.getPixels()); 242 tmp.unlockPixels(); 243 if (!read) { 244 return false; 245 } 246 247 tmp.swap(*bitmap); 248 return true; 249 } 250 251 void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y) { 252 SkAutoLockPixels alp(bitmap); 253 if (!bitmap.readyToDraw()) { 254 return; 255 } 256 GrPixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(), 257 bitmap.isOpaque()); 258 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 269 static void convert_matrixclip(GrContext* context, const SkMatrix& matrix, 270 const SkClipStack& clipStack, 271 const SkRegion& clipRegion, 272 const SkIPoint& origin) { 273 context->setMatrix(matrix); 274 275 SkGrClipIterator iter; 276 iter.reset(clipStack); 277 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)); 283 GrClip grc(&iter, GrIntToScalar(-origin.x()), GrIntToScalar(-origin.y()), 284 &bounds); 285 context->setClip(grc); 286 } 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 290 void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) { 291 if (fNeedPrepareRenderTarget || 292 fContext->getRenderTarget() != fRenderTarget) { 293 294 fContext->setRenderTarget(fRenderTarget); 295 SkASSERT(draw.fClipStack); 296 convert_matrixclip(fContext, *draw.fMatrix, 297 *draw.fClipStack, *draw.fClip, this->getOrigin()); 298 fNeedPrepareRenderTarget = false; 299 } 300 } 301 302 void SkGpuDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& clip, 303 const SkClipStack& clipStack) { 304 this->INHERITED::setMatrixClip(matrix, clip, clipStack); 305 // We don't need to set them now because the context may not reflect this device. 306 fNeedPrepareRenderTarget = true; 307 } 308 309 void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix, 310 const SkRegion& clip, const SkClipStack& clipStack) { 311 312 fContext->setRenderTarget(fRenderTarget); 313 314 this->INHERITED::gainFocus(canvas, matrix, clip, clipStack); 315 316 convert_matrixclip(fContext, matrix, clipStack, clip, this->getOrigin()); 317 318 if (fNeedClear) { 319 fContext->clear(NULL, 0x0); 320 fNeedClear = false; 321 } 322 } 323 324 bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) { 325 if (NULL != fTexture) { 326 paint->setTexture(kBitmapTextureIdx, fTexture); 327 return true; 328 } 329 return false; 330 } 331 332 /////////////////////////////////////////////////////////////////////////////// 333 334 SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch); 335 SK_COMPILE_ASSERT(SkShader::kDefault_BitmapType == 1, shader_type_mismatch); 336 SK_COMPILE_ASSERT(SkShader::kRadial_BitmapType == 2, shader_type_mismatch); 337 SK_COMPILE_ASSERT(SkShader::kSweep_BitmapType == 3, shader_type_mismatch); 338 SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4, 339 shader_type_mismatch); 340 SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 4, shader_type_mismatch); 341 342 static 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 350 bool SkGpuDevice::skPaint2GrPaintNoShader(const SkPaint& skPaint, 351 bool justAlpha, 352 GrPaint* grPaint, 353 bool constantColor) { 354 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)) { 364 SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");) 365 #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); 376 // justAlpha is currently set to true only if there is a texture, 377 // so constantColor should not also be true. 378 GrAssert(!constantColor); 379 } else { 380 grPaint->fColor = SkGr::SkColor2GrColor(skPaint.getColor()); 381 grPaint->setTexture(kShaderTextureIdx, NULL); 382 } 383 SkColorFilter* colorFilter = skPaint.getColorFilter(); 384 SkColor color; 385 SkXfermode::Mode filterMode; 386 if (colorFilter != NULL && colorFilter->asColorMode(&color, &filterMode)) { 387 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); 394 } 395 grPaint->resetColorFilter(); 396 return true; 397 } 398 399 bool SkGpuDevice::skPaint2GrPaintShader(const SkPaint& skPaint, 400 SkAutoCachedTexture* act, 401 const SkMatrix& ctm, 402 GrPaint* grPaint, 403 bool constantColor) { 404 405 SkASSERT(NULL != act); 406 407 SkShader* shader = skPaint.getShader(); 408 if (NULL == shader) { 409 return this->skPaint2GrPaintNoShader(skPaint, 410 false, 411 grPaint, 412 constantColor); 413 } else if (!this->skPaint2GrPaintNoShader(skPaint, true, grPaint, false)) { 414 return false; 415 } 416 417 SkPaint noAlphaPaint(skPaint); 418 noAlphaPaint.setAlpha(255); 419 shader->setContext(this->accessBitmap(false), noAlphaPaint, ctm); 420 421 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 428 GrSamplerState::SampleMode sampleMode = sk_bmp_type_to_sample_mode[bmptype]; 429 if (-1 == sampleMode) { 430 SkDebugf("shader->asABitmap() == kNone_BitmapType\n"); 431 return false; 432 } 433 GrSamplerState* sampler = grPaint->getTextureSampler(kShaderTextureIdx); 434 sampler->setSampleMode(sampleMode); 435 if (skPaint.isFilterBitmap()) { 436 sampler->setFilter(GrSamplerState::kBilinear_Filter); 437 } else { 438 sampler->setFilter(GrSamplerState::kNearest_Filter); 439 } 440 sampler->setWrapX(sk_tile_mode_to_grwrap(tileModes[0])); 441 sampler->setWrapY(sk_tile_mode_to_grwrap(tileModes[1])); 442 if (GrSamplerState::kRadial2_SampleMode == sampleMode) { 443 sampler->setRadial2Params(twoPointParams[0], 444 twoPointParams[1], 445 twoPointParams[2] < 0); 446 } 447 448 GrTexture* texture = act->set(this, bitmap, *sampler); 449 if (NULL == texture) { 450 SkDebugf("Couldn't convert bitmap to texture.\n"); 451 return false; 452 } 453 grPaint->setTexture(kShaderTextureIdx, texture); 454 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) { 465 GrScalar sx = GrFixedToScalar(GR_Fixed1 / bitmap.width()); 466 GrScalar sy = GrFixedToScalar(GR_Fixed1 / bitmap.height()); 467 matrix.postScale(sx, sy); 468 } else if (SkShader::kRadial_BitmapType == bmptype) { 469 GrScalar s = GrFixedToScalar(GR_Fixed1 / bitmap.width()); 470 matrix.postScale(s, s); 471 } 472 sampler->setMatrix(matrix); 473 474 return true; 475 } 476 477 /////////////////////////////////////////////////////////////////////////////// 478 479 class SkPositionSource { 480 public: 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 } 491 private: 492 const SkPoint* fPoints; 493 int fCount; 494 }; 495 496 class SkTexCoordSource { 497 public: 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 } 505 private: 506 const SkPoint* fCoords; 507 }; 508 509 class SkColorSource { 510 public: 511 SkColorSource(const SkColor* colors) : fColors(colors) {} 512 513 void writeValue(int i, GrColor* dstColor) const { 514 *dstColor = SkGr::SkColor2GrColor(fColors[i]); 515 } 516 private: 517 const SkColor* fColors; 518 }; 519 520 class SkIndexSource { 521 public: 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 532 private: 533 const uint16_t* fIndices; 534 int fCount; 535 }; 536 537 /////////////////////////////////////////////////////////////////////////////// 538 539 #if 0 // not currently being used so don't compile, 540 541 // can be used for positions or texture coordinates 542 543 class SkRectFanSource { 544 public: 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 } 556 private: 557 const SkRect& fRect; 558 }; 559 560 class SkIRectFanSource { 561 public: 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 } 573 private: 574 const SkIRect& fRect; 575 }; 576 577 class SkMatRectFanSource { 578 public: 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 } 600 private: 601 const SkRect& fRect; 602 const SkMatrix& fMatrix; 603 }; 604 605 #endif 606 607 /////////////////////////////////////////////////////////////////////////////// 608 609 void SkGpuDevice::clear(SkColor color) { 610 fContext->clear(NULL, color); 611 } 612 613 void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { 614 CHECK_SHOULD_DRAW(draw); 615 616 GrPaint grPaint; 617 SkAutoCachedTexture act; 618 if (!this->skPaint2GrPaintShader(paint, 619 &act, 620 *draw.fMatrix, 621 &grPaint, 622 true)) { 623 return; 624 } 625 626 fContext->drawPaint(grPaint); 627 } 628 629 // must be in SkCanvas::PointMode order 630 static const GrPrimitiveType gPointMode2PrimtiveType[] = { 631 kPoints_PrimitiveType, 632 kLines_PrimitiveType, 633 kLineStrip_PrimitiveType 634 }; 635 636 void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, 637 size_t count, const SkPoint pts[], const SkPaint& paint) { 638 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 651 GrPaint grPaint; 652 SkAutoCachedTexture act; 653 if (!this->skPaint2GrPaintShader(paint, 654 &act, 655 *draw.fMatrix, 656 &grPaint, 657 true)) { 658 return; 659 } 660 661 #if SK_SCALAR_IS_GR_SCALAR 662 fContext->drawVertices(grPaint, 663 gPointMode2PrimtiveType[mode], 664 count, 665 (GrPoint*)pts, 666 NULL, 667 NULL, 668 NULL, 669 0); 670 #else 671 fContext->drawCustomVertices(grPaint, 672 gPointMode2PrimtiveType[mode], 673 SkPositionSource(pts, count)); 674 #endif 675 } 676 677 /////////////////////////////////////////////////////////////////////////////// 678 679 void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, 680 const SkPaint& paint) { 681 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 // until we aa rotated rects... 697 if (!usePath && paint.isAntiAlias() && !draw.fMatrix->rectStaysRect()) { 698 usePath = true; 699 } 700 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; 710 if (!this->skPaint2GrPaintShader(paint, 711 &act, 712 *draw.fMatrix, 713 &grPaint, 714 true)) { 715 return; 716 } 717 fContext->drawRect(grPaint, rect, doStroke ? width : -1); 718 } 719 720 #include "SkMaskFilter.h" 721 #include "SkBounder.h" 722 723 static 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 752 // used to compute inverse view, if necessary 753 GrMatrix ivm = context->getMatrix(); 754 755 GrAutoMatrix avm(context, GrMatrix::I()); 756 757 const GrTextureDesc desc = { 758 kNone_GrTextureFlags, 759 kNone_GrAALevel, 760 dstM.fBounds.width(), 761 dstM.fBounds.height(), 762 kAlpha_8_GrPixelConfig 763 }; 764 765 GrTexture* texture = context->createUncachedTexture(desc, dstM.fImage, 766 dstM.fRowBytes); 767 if (NULL == texture) { 768 return false; 769 } 770 771 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); 779 texture->unref(); 780 grp->getMaskSampler(MASK_IDX)->setClampNoFilter(); 781 782 GrRect d; 783 d.setLTRB(GrIntToScalar(dstM.fBounds.fLeft), 784 GrIntToScalar(dstM.fBounds.fTop), 785 GrIntToScalar(dstM.fBounds.fRight), 786 GrIntToScalar(dstM.fBounds.fBottom)); 787 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); 794 return true; 795 } 796 797 void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, 798 const SkPaint& paint, const SkMatrix* prePathMatrix, 799 bool pathIsMutable) { 800 CHECK_SHOULD_DRAW(draw); 801 802 GrPaint grPaint; 803 SkAutoCachedTexture act; 804 if (!this->skPaint2GrPaintShader(paint, 805 &act, 806 *draw.fMatrix, 807 &grPaint, 808 true)) { 809 return; 810 } 811 812 // BEGIN lift from SkDraw::drawPath() 813 814 SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath); 815 bool doFill = true; 816 SkPath tmpPath; 817 818 if (prePathMatrix) { 819 SkPath* result = pathPtr; 820 821 if (!pathIsMutable) { 822 result = &tmpPath; 823 pathIsMutable = true; 824 } 825 // 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; 829 } 830 // at this point we're done with prePathMatrix 831 SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) 832 833 // 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)) { 849 doFill = paint.getFillPath(*pathPtr, &tmpPath); 850 pathPtr = &tmpPath; 851 } 852 853 // END lift from SkDraw::drawPath() 854 855 if (paint.getMaskFilter()) { 856 // 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 860 pathPtr->transform(*draw.fMatrix, devPathPtr); 861 862 drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(), 863 *draw.fMatrix, *draw.fClip, draw.fBounder, &grPaint); 864 return; 865 } 866 867 GrPathFill fill = kHairLine_PathFill; 868 869 if (doFill) { 870 switch (pathPtr->getFillType()) { 871 case SkPath::kWinding_FillType: 872 fill = kWinding_PathFill; 873 break; 874 case SkPath::kEvenOdd_FillType: 875 fill = kEvenOdd_PathFill; 876 break; 877 case SkPath::kInverseWinding_FillType: 878 fill = kInverseWinding_PathFill; 879 break; 880 case SkPath::kInverseEvenOdd_FillType: 881 fill = kInverseEvenOdd_PathFill; 882 break; 883 default: 884 SkDebugf("Unsupported path fill type\n"); 885 return; 886 } 887 } 888 889 fContext->drawPath(grPaint, *pathPtr, fill); 890 } 891 892 void 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 906 GrPaint grPaint; 907 if (!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) { 908 return; 909 } 910 GrSamplerState* sampler = grPaint.getTextureSampler(kBitmapTextureIdx); 911 if (paint.isFilterBitmap()) { 912 sampler->setFilter(GrSamplerState::kBilinear_Filter); 913 } else { 914 sampler->setFilter(GrSamplerState::kNearest_Filter); 915 } 916 917 const int maxTextureDim = fContext->getMaxTextureDimension(); 918 if (bitmap.getTexture() || (bitmap.width() <= maxTextureDim && 919 bitmap.height() <= maxTextureDim)) { 920 // take the fast case 921 this->internalDrawBitmap(draw, bitmap, srcRect, m, &grPaint); 922 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 944 int nx = bitmap.width() / maxTextureDim; 945 int ny = bitmap.height() / maxTextureDim; 946 for (int x = 0; x <= nx; x++) { 947 for (int y = 0; y <= ny; y++) { 948 SkIRect tileR; 949 tileR.set(x * maxTextureDim, y * maxTextureDim, 950 (x + 1) * maxTextureDim, (y + 1) * maxTextureDim); 951 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 } 971 this->internalDrawBitmap(draw, tmpB, srcR, tmpM, &grPaint); 972 } 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 * 981 * internalDrawBitmap assumes that the specified bitmap will fit in a texture 982 * and that non-texture portion of the GrPaint has already been setup. 983 */ 984 void SkGpuDevice::internalDrawBitmap(const SkDraw& draw, 985 const SkBitmap& bitmap, 986 const SkIRect& srcRect, 987 const SkMatrix& m, 988 GrPaint* grPaint) { 989 SkASSERT(bitmap.width() <= fContext->getMaxTextureDimension() && 990 bitmap.height() <= fContext->getMaxTextureDimension()); 991 992 SkAutoLockPixels alp(bitmap); 993 if (!bitmap.getTexture() && !bitmap.readyToDraw()) { 994 return; 995 } 996 997 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()); 1003 1004 GrTexture* texture; 1005 SkAutoCachedTexture act(this, bitmap, *sampler, &texture); 1006 if (NULL == texture) { 1007 return; 1008 } 1009 1010 grPaint->setTexture(kShaderTextureIdx, texture); 1011 1012 GrRect dstRect = SkRect::MakeWH(GrIntToScalar(srcRect.width()), 1013 GrIntToScalar(srcRect.height())); 1014 GrRect paintRect; 1015 paintRect.setLTRB(GrFixedToScalar((srcRect.fLeft << 16) / bitmap.width()), 1016 GrFixedToScalar((srcRect.fTop << 16) / bitmap.height()), 1017 GrFixedToScalar((srcRect.fRight << 16) / bitmap.width()), 1018 GrFixedToScalar((srcRect.fBottom << 16) / bitmap.height())); 1019 1020 if (GrSamplerState::kNearest_Filter != sampler->getFilter() && 1021 (srcRect.width() < bitmap.width() || 1022 srcRect.height() < bitmap.height())) { 1023 // 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); 1042 sampler->setTextureDomain(textureDomain); 1043 } 1044 1045 fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m); 1046 } 1047 1048 void 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 1057 GrPaint grPaint; 1058 if(!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) { 1059 return; 1060 } 1061 1062 GrAutoMatrix avm(fContext, GrMatrix::I()); 1063 1064 GrSamplerState* sampler = grPaint.getTextureSampler(kBitmapTextureIdx); 1065 1066 GrTexture* texture; 1067 sampler->setClampNoFilter(); 1068 SkAutoCachedTexture act(this, bitmap, *sampler, &texture); 1069 1070 grPaint.setTexture(kBitmapTextureIdx, texture); 1071 1072 fContext->drawRectToRect(grPaint, 1073 GrRect::MakeXYWH(GrIntToScalar(left), 1074 GrIntToScalar(top), 1075 GrIntToScalar(bitmap.width()), 1076 GrIntToScalar(bitmap.height())), 1077 GrRect::MakeWH(GR_Scalar1, GR_Scalar1)); 1078 } 1079 1080 void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* dev, 1081 int x, int y, const SkPaint& paint) { 1082 CHECK_SHOULD_DRAW(draw); 1083 1084 GrPaint grPaint; 1085 if (!((SkGpuDevice*)dev)->bindDeviceAsTexture(&grPaint) || 1086 !this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) { 1087 return; 1088 } 1089 1090 SkASSERT(NULL != grPaint.getTexture(0)); 1091 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 1098 grPaint.getTextureSampler(kBitmapTextureIdx)->setClampNoFilter(); 1099 1100 fContext->drawRectToRect(grPaint, 1101 GrRect::MakeXYWH(GrIntToScalar(x), 1102 GrIntToScalar(y), 1103 GrIntToScalar(w), 1104 GrIntToScalar(h)), 1105 GrRect::MakeWH(GR_Scalar1, GR_Scalar1)); 1106 } 1107 1108 /////////////////////////////////////////////////////////////////////////////// 1109 1110 // must be in SkCanvas::VertexMode order 1111 static const GrPrimitiveType gVertexMode2PrimitiveType[] = { 1112 kTriangles_PrimitiveType, 1113 kTriangleStrip_PrimitiveType, 1114 kTriangleFan_PrimitiveType, 1115 }; 1116 1117 void 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 1125 GrPaint grPaint; 1126 SkAutoCachedTexture act; 1127 // we ignore the shader if texs is null. 1128 if (NULL == texs) { 1129 if (!this->skPaint2GrPaintNoShader(paint, 1130 false, 1131 &grPaint, 1132 NULL == colors)) { 1133 return; 1134 } 1135 } else { 1136 if (!this->skPaint2GrPaintShader(paint, &act, 1137 *draw.fMatrix, 1138 &grPaint, 1139 NULL == colors)) { 1140 return; 1141 } 1142 } 1143 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 } 1153 } 1154 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); 1180 } 1181 } 1182 1183 /////////////////////////////////////////////////////////////////////////////// 1184 1185 static void GlyphCacheAuxProc(void* data) { 1186 delete (GrFontScaler*)data; 1187 } 1188 1189 static 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 1202 static 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 } 1212 1213 /* 1214 * What should we do with fy? (assuming horizontal/latin text) 1215 * 1216 * 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... 1226 */ 1227 fy = SkFixedFloorToFixed(fy); 1228 1229 procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), fx, 0), 1230 SkFixedFloorToFixed(fx), fy, 1231 procs->fFontScaler); 1232 } 1233 1234 SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) { 1235 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 1249 void 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 { 1258 SkDraw myDraw(draw); 1259 1260 GrPaint grPaint; 1261 SkAutoCachedTexture act; 1262 1263 if (!this->skPaint2GrPaintShader(paint, 1264 &act, 1265 *draw.fMatrix, 1266 &grPaint, 1267 true)) { 1268 return; 1269 } 1270 GrTextContext context(fContext, grPaint, draw.fExtMatrix); 1271 myDraw.fProcs = this->initDrawForText(&context); 1272 this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint); 1273 } 1274 } 1275 1276 void 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 { 1287 SkDraw myDraw(draw); 1288 1289 GrPaint grPaint; 1290 SkAutoCachedTexture act; 1291 if (!this->skPaint2GrPaintShader(paint, 1292 &act, 1293 *draw.fMatrix, 1294 &grPaint, 1295 true)) { 1296 return; 1297 } 1298 1299 GrTextContext context(fContext, grPaint, draw.fExtMatrix); 1300 myDraw.fProcs = this->initDrawForText(&context); 1301 this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY, 1302 scalarsPerPos, paint); 1303 } 1304 } 1305 1306 void 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 1317 bool 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 1342 SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap, 1343 const GrSamplerState& sampler, 1344 GrTexture** texture, 1345 bool forDeviceRenderTarget) { 1346 GrTexture* newTexture = NULL; 1347 GrTextureEntry* entry = NULL; 1348 GrContext* ctx = this->context(); 1349 1350 if (forDeviceRenderTarget) { 1351 const GrTextureDesc desc = { 1352 kRenderTarget_GrTextureFlagBit, 1353 kNone_GrAALevel, 1354 bitmap.width(), 1355 bitmap.height(), 1356 SkGr::Bitmap2PixelConfig(bitmap) 1357 }; 1358 entry = ctx->lockKeylessTexture(desc); 1359 } else { 1360 uint32_t p0, p1; 1361 p0 = bitmap.getGenerationID(); 1362 p1 = bitmap.pixelRefOffset(); 1363 1364 GrTextureKey key(p0, p1, bitmap.width(), bitmap.height()); 1365 entry = ctx->findAndLockTexture(&key, sampler); 1366 1367 if (NULL == entry) { 1368 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 } 1373 } 1374 } 1375 1376 if (NULL != entry) { 1377 newTexture = entry->texture(); 1378 if (texture) { 1379 *texture = newTexture; 1380 } 1381 } 1382 return (TexCache*)entry; 1383 } 1384 1385 void SkGpuDevice::unlockCachedTexture(TexCache* cache) { 1386 this->context()->unlockTexture((GrTextureEntry*)cache); 1387 } 1388 1389 /////////////////////////////////////////////////////////////////////////////// 1390 1391 SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, 1392 GrRenderTarget* rootRenderTarget) { 1393 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 } 1405 1406 fContext = context; 1407 context->ref(); 1408 1409 fRootTexture = NULL; 1410 } 1411 1412 SkGpuDeviceFactory::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 1423 fContext = context; 1424 context->ref(); 1425 } 1426 1427 SkGpuDeviceFactory::~SkGpuDeviceFactory() { 1428 fContext->unref(); 1429 fRootRenderTarget->unref(); 1430 GrSafeUnref(fRootTexture); 1431 } 1432 1433 SkDevice* 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); 1439 return new SkGpuDevice(fContext, bm, isLayer ? NULL : fRootRenderTarget); 1440 } 1441