Home | History | Annotate | Download | only in gpu
      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