gfx/skia/trunk/src/core/SkBitmapProcShader.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     2 /*
     3  * Copyright 2011 Google Inc.
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
     8 #include "SkColorPriv.h"
     9 #include "SkReadBuffer.h"
    10 #include "SkWriteBuffer.h"
    11 #include "SkPixelRef.h"
    12 #include "SkErrorInternals.h"
    13 #include "SkBitmapProcShader.h"
    15 #if SK_SUPPORT_GPU
    16 #include "effects/GrSimpleTextureEffect.h"
    17 #include "effects/GrBicubicEffect.h"
    18 #endif
    20 bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
    21     switch (bm.colorType()) {
    22         case kAlpha_8_SkColorType:
    23         case kRGB_565_SkColorType:
    24         case kIndex_8_SkColorType:
    25         case kPMColor_SkColorType:
    26     //        if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
    27                 return true;
    28         default:
    29             break;
    30     }
    31     return false;
    32 }
    34 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
    35                                        TileMode tmx, TileMode tmy) {
    36     fRawBitmap = src;
    37     fState.fTileModeX = (uint8_t)tmx;
    38     fState.fTileModeY = (uint8_t)tmy;
    39     fFlags = 0; // computed in setContext
    40 }
    42 SkBitmapProcShader::SkBitmapProcShader(SkReadBuffer& buffer)
    43         : INHERITED(buffer) {
    44     buffer.readBitmap(&fRawBitmap);
    45     fRawBitmap.setImmutable();
    46     fState.fTileModeX = buffer.readUInt();
    47     fState.fTileModeY = buffer.readUInt();
    48     fFlags = 0; // computed in setContext
    49 }
    51 SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
    52                                                    SkMatrix* texM,
    53                                                    TileMode xy[]) const {
    54     if (texture) {
    55         *texture = fRawBitmap;
    56     }
    57     if (texM) {
    58         texM->reset();
    59     }
    60     if (xy) {
    61         xy[0] = (TileMode)fState.fTileModeX;
    62         xy[1] = (TileMode)fState.fTileModeY;
    63     }
    64     return kDefault_BitmapType;
    65 }
    67 void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const {
    68     this->INHERITED::flatten(buffer);
    70     buffer.writeBitmap(fRawBitmap);
    71     buffer.writeUInt(fState.fTileModeX);
    72     buffer.writeUInt(fState.fTileModeY);
    73 }
    75 static bool only_scale_and_translate(const SkMatrix& matrix) {
    76     unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    77     return (matrix.getType() & ~mask) == 0;
    78 }
    80 bool SkBitmapProcShader::isOpaque() const {
    81     return fRawBitmap.isOpaque();
    82 }
    84 static bool valid_for_drawing(const SkBitmap& bm) {
    85     if (0 == bm.width() || 0 == bm.height()) {
    86         return false;   // nothing to draw
    87     }
    88     if (NULL == bm.pixelRef()) {
    89         return false;   // no pixels to read
    90     }
    91     if (kIndex_8_SkColorType == bm.colorType()) {
    92         // ugh, I have to lock-pixels to inspect the colortable
    93         SkAutoLockPixels alp(bm);
    94         if (!bm.getColorTable()) {
    95             return false;
    96         }
    97     }
    98     return true;
    99 }
   101 bool SkBitmapProcShader::setContext(const SkBitmap& device,
   102                                     const SkPaint& paint,
   103                                     const SkMatrix& matrix) {
   104     if (!fRawBitmap.getTexture() && !valid_for_drawing(fRawBitmap)) {
   105         return false;
   106     }
   108     // do this first, so we have a correct inverse matrix
   109     if (!this->INHERITED::setContext(device, paint, matrix)) {
   110         return false;
   111     }
   113     fState.fOrigBitmap = fRawBitmap;
   114     if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
   115         this->INHERITED::endContext();
   116         return false;
   117     }
   119     const SkBitmap& bitmap = *fState.fBitmap;
   120     bool bitmapIsOpaque = bitmap.isOpaque();
   122     // update fFlags
   123     uint32_t flags = 0;
   124     if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
   125         flags |= kOpaqueAlpha_Flag;
   126     }
   128     switch (bitmap.colorType()) {
   129         case kRGB_565_SkColorType:
   130             flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
   131             break;
   132         case kIndex_8_SkColorType:
   133         case kPMColor_SkColorType:
   134             if (bitmapIsOpaque) {
   135                 flags |= kHasSpan16_Flag;
   136             }
   137             break;
   138         case kAlpha_8_SkColorType:
   139             break;  // never set kHasSpan16_Flag
   140         default:
   141             break;
   142     }
   144     if (paint.isDither() && bitmap.colorType() != kRGB_565_SkColorType) {
   145         // gradients can auto-dither in their 16bit sampler, but we don't so
   146         // we clear the flag here.
   147         flags &= ~kHasSpan16_Flag;
   148     }
   150     // if we're only 1-pixel high, and we don't rotate, then we can claim this
   151     if (1 == bitmap.height() &&
   152             only_scale_and_translate(this->getTotalInverse())) {
   153         flags |= kConstInY32_Flag;
   154         if (flags & kHasSpan16_Flag) {
   155             flags |= kConstInY16_Flag;
   156         }
   157     }
   159     fFlags = flags;
   160     return true;
   161 }
   163 void SkBitmapProcShader::endContext() {
   164     fState.endContext();
   165     this->INHERITED::endContext();
   166 }
   168 #define BUF_MAX     128
   170 #define TEST_BUFFER_OVERRITEx
   172 #ifdef TEST_BUFFER_OVERRITE
   173     #define TEST_BUFFER_EXTRA   32
   174     #define TEST_PATTERN    0x88888888
   175 #else
   176     #define TEST_BUFFER_EXTRA   0
   177 #endif
   179 void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
   180     const SkBitmapProcState& state = fState;
   181     if (state.getShaderProc32()) {
   182         state.getShaderProc32()(state, x, y, dstC, count);
   183         return;
   184     }
   186     uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
   187     SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
   188     SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
   189     int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
   191     SkASSERT(state.fBitmap->getPixels());
   192     SkASSERT(state.fBitmap->pixelRef() == NULL ||
   193              state.fBitmap->pixelRef()->isLocked());
   195     for (;;) {
   196         int n = count;
   197         if (n > max) {
   198             n = max;
   199         }
   200         SkASSERT(n > 0 && n < BUF_MAX*2);
   201 #ifdef TEST_BUFFER_OVERRITE
   202         for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
   203             buffer[BUF_MAX + i] = TEST_PATTERN;
   204         }
   205 #endif
   206         mproc(state, buffer, n, x, y);
   207 #ifdef TEST_BUFFER_OVERRITE
   208         for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
   209             SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
   210         }
   211 #endif
   212         sproc(state, buffer, n, dstC);
   214         if ((count -= n) == 0) {
   215             break;
   216         }
   217         SkASSERT(count > 0);
   218         x += n;
   219         dstC += n;
   220     }
   221 }
   223 SkShader::ShadeProc SkBitmapProcShader::asAShadeProc(void** ctx) {
   224     if (fState.getShaderProc32()) {
   225         *ctx = &fState;
   226         return (ShadeProc)fState.getShaderProc32();
   227     }
   228     return NULL;
   229 }
   231 void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
   232     const SkBitmapProcState& state = fState;
   233     if (state.getShaderProc16()) {
   234         state.getShaderProc16()(state, x, y, dstC, count);
   235         return;
   236     }
   238     uint32_t buffer[BUF_MAX];
   239     SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
   240     SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16();
   241     int max = fState.maxCountForBufferSize(sizeof(buffer));
   243     SkASSERT(state.fBitmap->getPixels());
   244     SkASSERT(state.fBitmap->pixelRef() == NULL ||
   245              state.fBitmap->pixelRef()->isLocked());
   247     for (;;) {
   248         int n = count;
   249         if (n > max) {
   250             n = max;
   251         }
   252         mproc(state, buffer, n, x, y);
   253         sproc(state, buffer, n, dstC);
   255         if ((count -= n) == 0) {
   256             break;
   257         }
   258         x += n;
   259         dstC += n;
   260     }
   261 }
   263 ///////////////////////////////////////////////////////////////////////////////
   265 #include "SkUnPreMultiply.h"
   266 #include "SkColorShader.h"
   267 #include "SkEmptyShader.h"
   269 // returns true and set color if the bitmap can be drawn as a single color
   270 // (for efficiency)
   271 static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
   272     if (1 != bm.width() || 1 != bm.height()) {
   273         return false;
   274     }
   276     SkAutoLockPixels alp(bm);
   277     if (!bm.readyToDraw()) {
   278         return false;
   279     }
   281     switch (bm.colorType()) {
   282         case kPMColor_SkColorType:
   283             *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
   284             return true;
   285         case kRGB_565_SkColorType:
   286             *color = SkPixel16ToColor(*bm.getAddr16(0, 0));
   287             return true;
   288         case kIndex_8_SkColorType:
   289             *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
   290             return true;
   291         default: // just skip the other configs for now
   292             break;
   293     }
   294     return false;
   295 }
   297 static bool bitmapIsTooBig(const SkBitmap& bm) {
   298     // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
   299     // communicates between its matrix-proc and its sampler-proc. Until we can
   300     // widen that, we have to reject bitmaps that are larger.
   301     //
   302     const int maxSize = 65535;
   304     return bm.width() > maxSize || bm.height() > maxSize;
   305 }
   307 SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
   308         SkShader::TileMode tmy, SkTBlitterAllocator* allocator) {
   309     SkShader* shader;
   310     SkColor color;
   311     if (src.isNull() || bitmapIsTooBig(src)) {
   312         if (NULL == allocator) {
   313             shader = SkNEW(SkEmptyShader);
   314         } else {
   315             shader = allocator->createT<SkEmptyShader>();
   316         }
   317     }
   318     else if (canUseColorShader(src, &color)) {
   319         if (NULL == allocator) {
   320             shader = SkNEW_ARGS(SkColorShader, (color));
   321         } else {
   322             shader = allocator->createT<SkColorShader>(color);
   323         }
   324     } else {
   325         if (NULL == allocator) {
   326             shader = SkNEW_ARGS(SkBitmapProcShader, (src, tmx, tmy));
   327         } else {
   328             shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy);
   329         }
   330     }
   331     return shader;
   332 }
   334 ///////////////////////////////////////////////////////////////////////////////
   336 #ifndef SK_IGNORE_TO_STRING
   337 void SkBitmapProcShader::toString(SkString* str) const {
   338     static const char* gTileModeName[SkShader::kTileModeCount] = {
   339         "clamp", "repeat", "mirror"
   340     };
   342     str->append("BitmapShader: (");
   344     str->appendf("(%s, %s)",
   345                  gTileModeName[fState.fTileModeX],
   346                  gTileModeName[fState.fTileModeY]);
   348     str->append(" ");
   349     fRawBitmap.toString(str);
   351     this->INHERITED::toString(str);
   353     str->append(")");
   354 }
   355 #endif
   357 ///////////////////////////////////////////////////////////////////////////////
   359 #if SK_SUPPORT_GPU
   361 #include "GrTextureAccess.h"
   362 #include "effects/GrSimpleTextureEffect.h"
   363 #include "SkGr.h"
   365 // Note that this will return -1 if either matrix is perspective.
   366 static SkScalar get_combined_min_stretch(const SkMatrix& viewMatrix, const SkMatrix& localMatrix) {
   367     if (localMatrix.isIdentity()) {
   368         return viewMatrix.getMinStretch();
   369     } else {
   370         SkMatrix combined;
   371         combined.setConcat(viewMatrix, localMatrix);
   372         return combined.getMinStretch();
   373     }
   374 }
   376 GrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
   377     SkMatrix matrix;
   378     matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height());
   380     SkMatrix lmInverse;
   381     if (!this->getLocalMatrix().invert(&lmInverse)) {
   382         return NULL;
   383     }
   384     matrix.preConcat(lmInverse);
   386     SkShader::TileMode tm[] = {
   387         (TileMode)fState.fTileModeX,
   388         (TileMode)fState.fTileModeY,
   389     };
   391     // Must set wrap and filter on the sampler before requesting a texture. In two places below
   392     // we check the matrix scale factors to determine how to interpret the filter quality setting.
   393     // This completely ignores the complexity of the drawVertices case where explicit local coords
   394     // are provided by the caller.
   395     SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel();
   396     GrTextureParams::FilterMode textureFilterMode;
   397     switch(paintFilterLevel) {
   398         case SkPaint::kNone_FilterLevel:
   399             textureFilterMode = GrTextureParams::kNone_FilterMode;
   400             break;
   401         case SkPaint::kLow_FilterLevel:
   402             textureFilterMode = GrTextureParams::kBilerp_FilterMode;
   403             break;
   404         case SkPaint::kMedium_FilterLevel:
   405             if (get_combined_min_stretch(context->getMatrix(), this->getLocalMatrix()) <
   406                 SK_Scalar1) {
   407                 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
   408             } else {
   409                 // Don't trigger MIP level generation unnecessarily.
   410                 textureFilterMode = GrTextureParams::kBilerp_FilterMode;
   411             }
   412             break;
   413         case SkPaint::kHigh_FilterLevel:
   414             // Minification can look bad with bicubic filtering.
   415             if (get_combined_min_stretch(context->getMatrix(), this->getLocalMatrix()) >=
   416                 SK_Scalar1) {
   417                 // fall back to no filtering here; we will install another shader that will do the
   418                 // HQ filtering.
   419                 textureFilterMode = GrTextureParams::kNone_FilterMode;
   420             } else {
   421                 // Fall back to MIP-mapping.
   422                 paintFilterLevel = SkPaint::kMedium_FilterLevel;
   423                 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
   424             }
   425             break;
   426         default:
   427             SkErrorInternals::SetError( kInvalidPaint_SkError,
   428                                         "Sorry, I don't understand the filtering "
   429                                         "mode you asked for.  Falling back to "
   430                                         "MIPMaps.");
   431             textureFilterMode = GrTextureParams::kMipMap_FilterMode;
   432             break;
   434     }
   435     GrTextureParams params(tm, textureFilterMode);
   436     GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, fRawBitmap, &params);
   438     if (NULL == texture) {
   439         SkErrorInternals::SetError( kInternalError_SkError,
   440                                     "Couldn't convert bitmap to texture.");
   441         return NULL;
   442     }
   444     GrEffectRef* effect = NULL;
   445     if (paintFilterLevel == SkPaint::kHigh_FilterLevel) {
   446         effect = GrBicubicEffect::Create(texture, matrix, tm);
   447     } else {
   448         effect = GrSimpleTextureEffect::Create(texture, matrix, params);
   449     }
   450     GrUnlockAndUnrefCachedBitmapTexture(texture);
   451     return effect;
   452 }
   453 #endif

mercurial