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.

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

mercurial