diff options
author | bsalomon <bsalomon@google.com> | 2015-11-09 10:06:06 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-09 10:06:06 -0800 |
commit | 5c1262d7f7e25282808653b9b70f097d2bbfa2fd (patch) | |
tree | 7c50f122375dc11e401a6ec73db9770450fdfccf /gm/bleed.cpp | |
parent | edce2a8576c4f701674d925731e10e569e9dc9b0 (diff) |
Rewrite bleed GM bmp/img generators and change oversized texture case
Makes it so that the oversized-texture/bmp case doesn't run on the CPU and makes it so that the subrect rendered is adjacent to the texture pad area on the bottom/right edges.
Review URL: https://codereview.chromium.org/1424473006
Diffstat (limited to 'gm/bleed.cpp')
-rw-r--r-- | gm/bleed.cpp | 503 |
1 files changed, 299 insertions, 204 deletions
diff --git a/gm/bleed.cpp b/gm/bleed.cpp index 37a38442fd..85ae2f49d1 100644 --- a/gm/bleed.cpp +++ b/gm/bleed.cpp @@ -19,197 +19,262 @@ #include "SkGr.h" #endif -static void draw_bitmap_rect(SkCanvas* canvas, const SkBitmap& bitmap, const SkImage*, - const SkRect& src, const SkRect& dst, - const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) { - canvas->drawBitmapRect(bitmap, src, dst, paint, constraint); -} - -static void draw_image_rect(SkCanvas* canvas, const SkBitmap&, const SkImage* image, - const SkRect& src, const SkRect& dst, - const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) { - canvas->drawImageRect(image, src, dst, paint, constraint); -} - -// Upload the tight-fitting sw-backed bitmap to a loose-fitting gpu-backed texture before drawing -static void draw_texture_bitmap_rect(SkCanvas* canvas, const SkBitmap& bitmap, const SkImage*, - const SkRect& src, const SkRect& dst, - const SkPaint* paint, - SkCanvas::SrcRectConstraint constraint) { - GrContext* context = canvas->getGrContext(); - if (!context) { - // For non-GPU canvases fallback to drawing the bitmap directly. - canvas->drawBitmapRect(bitmap, src, dst, paint, constraint); - return; - } -#if SK_SUPPORT_GPU - GrSurfaceDesc desc; - desc.fConfig = kAlpha_8_SkColorType == bitmap.colorType() ? kAlpha_8_GrPixelConfig : - kSkia8888_GrPixelConfig; - // Add some padding to the right and beneath the bitmap contents to exercise the case where - // the texture is larger than the bitmap. Outsets chosen to be small and different. - desc.fWidth = bitmap.width() + 16; - desc.fHeight = bitmap.height() + 23; - SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc, true)); - if (!texture) { - return; - } - // Init the whole texture to 0 in the alpha case or solid green in the 32bit rgba case. - SkAutoLockPixels al(bitmap); - if (kAlpha_8_GrPixelConfig == texture->config()) { - SkAutoMalloc pixels(texture->width() * texture->height()); - memset(pixels.get(), 0, texture->width() * texture->height()); - texture->writePixels(0, 0, texture->width(), texture->height(), desc.fConfig, pixels.get(), - 0); - } else { - SkAutoMalloc pixels(texture->width() * texture->height() * sizeof(uint32_t)); - SkOpts::memset32((uint32_t*)pixels.get(), 0xFF00FF00, texture->width()*texture->height()); - texture->writePixels(0, 0, texture->width(), texture->height(), desc.fConfig, pixels.get(), - 0); - } - - // Upload the bitmap contents to the upper left. - texture->writePixels(0, 0, bitmap.width(), bitmap.height(), desc.fConfig, bitmap.getPixels(), - bitmap.rowBytes()); - - // Wrap the texture in a bitmap and draw it. - SkBitmap textureBmp; - GrWrapTextureInBitmap(texture, bitmap.width(), bitmap.height(), true, &textureBmp); - canvas->drawBitmapRect(textureBmp, src, dst, paint, constraint); -#endif -} +/** Holds either a bitmap or image to be rendered and a rect that indicates what part of the bitmap + or image should be tested by the GM. The area outside of the rect is present to check + for bleed due to filtering/blurring. */ +struct TestPixels { + enum Type { + kBitmap, + kImage + }; + Type fType; + SkBitmap fBitmap; + SkAutoTUnref<SkImage> fImage; + SkIRect fRect; // The region of the bitmap/image that should be rendered. +}; -// Create a black&white checked texture with 2 1-pixel rings -// around the outside edge. The inner ring is red and the outer ring is blue. -static void make_ringed_color_bitmap(SkBitmap* result, int width, int height) { +/** Creates a bitmap with two one-pixel rings around a checkerboard. The checkerboard is 2x2 + logically where each check has as many pixels as is necessary to fill the interior. The rect + to draw is set to the checkerboard portion. */ +template<typename PIXEL_TYPE> +bool make_ringed_bitmap(GrContext*, TestPixels* result, int width, int height, + SkColorType ct, SkAlphaType at, + PIXEL_TYPE outerRingColor, PIXEL_TYPE innerRingColor, + PIXEL_TYPE checkColor1, PIXEL_TYPE checkColor2) { SkASSERT(0 == width % 2 && 0 == height % 2); + SkASSERT(width >= 6 && height >= 6); - static const SkPMColor kRed = SkPreMultiplyColor(SK_ColorRED); - static const SkPMColor kBlue = SkPreMultiplyColor(SK_ColorBLUE); - static const SkPMColor kBlack = SkPreMultiplyColor(SK_ColorBLACK); - static const SkPMColor kWhite = SkPreMultiplyColor(SK_ColorWHITE); - - result->allocN32Pixels(width, height, true); + result->fType = TestPixels::kBitmap; + SkImageInfo info = SkImageInfo::Make(width, height, ct, at); + size_t rowBytes = SkAlign4(info.minRowBytes()); + result->fBitmap.allocPixels(info, rowBytes); - SkPMColor* scanline = result->getAddr32(0, 0); + PIXEL_TYPE* scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, 0); for (int x = 0; x < width; ++x) { - scanline[x] = kBlue; + scanline[x] = outerRingColor; } - scanline = result->getAddr32(0, 1); - scanline[0] = kBlue; + scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, 1); + scanline[0] = outerRingColor; for (int x = 1; x < width - 1; ++x) { - scanline[x] = kRed; + scanline[x] = innerRingColor; } - scanline[width-1] = kBlue; - - for (int y = 2; y < height/2; ++y) { - scanline = result->getAddr32(0, y); - scanline[0] = kBlue; - scanline[1] = kRed; - for (int x = 2; x < width/2; ++x) { - scanline[x] = kBlack; + scanline[width - 1] = outerRingColor; + + for (int y = 2; y < height / 2; ++y) { + scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, y); + scanline[0] = outerRingColor; + scanline[1] = innerRingColor; + for (int x = 2; x < width / 2; ++x) { + scanline[x] = checkColor1; } - for (int x = width/2; x < width-2; ++x) { - scanline[x] = kWhite; + for (int x = width / 2; x < width - 2; ++x) { + scanline[x] = checkColor2; } - scanline[width-2] = kRed; - scanline[width-1] = kBlue; + scanline[width - 2] = innerRingColor; + scanline[width - 1] = outerRingColor; } - for (int y = height/2; y < height-2; ++y) { - scanline = result->getAddr32(0, y); - scanline[0] = kBlue; - scanline[1] = kRed; - for (int x = 2; x < width/2; ++x) { - scanline[x] = kWhite; + for (int y = height / 2; y < height - 2; ++y) { + scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, y); + scanline[0] = outerRingColor; + scanline[1] = innerRingColor; + for (int x = 2; x < width / 2; ++x) { + scanline[x] = checkColor2; } - for (int x = width/2; x < width-2; ++x) { - scanline[x] = kBlack; + for (int x = width / 2; x < width - 2; ++x) { + scanline[x] = checkColor1; } - scanline[width-2] = kRed; - scanline[width-1] = kBlue; + scanline[width - 2] = innerRingColor; + scanline[width - 1] = outerRingColor; } - scanline = result->getAddr32(0, height-2); - scanline[0] = kBlue; + scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, height - 2); + scanline[0] = outerRingColor; for (int x = 1; x < width - 1; ++x) { - scanline[x] = kRed; + scanline[x] = innerRingColor; } - scanline[width-1] = kBlue; + scanline[width - 1] = outerRingColor; - scanline = result->getAddr32(0, height-1); + scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, height - 1); for (int x = 0; x < width; ++x) { - scanline[x] = kBlue; + scanline[x] = outerRingColor; } - result->setImmutable(); + result->fBitmap.setImmutable(); + result->fRect.set(2, 2, width - 2, height - 2); + return true; +} + +/** Create a black and white checked texture with 2 1-pixel rings around the outside edge. + The inner ring is red and the outer ring is blue. */ +static bool make_ringed_color_bitmap(GrContext* ctx, TestPixels* result, int width, int height) { + static const SkPMColor kBlue = SkPreMultiplyColor(SK_ColorBLUE); + static const SkPMColor kRed = SkPreMultiplyColor(SK_ColorRED); + static const SkPMColor kBlack = SkPreMultiplyColor(SK_ColorBLACK); + static const SkPMColor kWhite = SkPreMultiplyColor(SK_ColorWHITE); + return make_ringed_bitmap<SkPMColor>(ctx, result, width, height, kBGRA_8888_SkColorType, + kPremul_SkAlphaType, kBlue, kRed, kBlack, kWhite); } /** Makes a alpha bitmap with 1 wide rect/ring of 0s, an inset of 1s, and the interior is a 2x2 checker board of 3/4 and 1/2. The inner checkers are large enough to fill the interior with the 2x2 checker grid. */ -static void make_ringed_alpha_bitmap(SkBitmap* result, int width, int height) { - SkASSERT(0 == width % 2 && 0 == height % 2); +static bool make_ringed_alpha_bitmap(GrContext* ctx, TestPixels* result, int width, int height) { + static const uint8_t kZero = 0x00; + static const uint8_t kHalf = 0x80; + static const uint8_t k3Q = 0xC0; + static const uint8_t kOne = 0xFF; + return make_ringed_bitmap<uint8_t>(ctx, result, width, height, kAlpha_8_SkColorType, + kPremul_SkAlphaType, kZero, kOne, k3Q, kHalf); +} - static const SkPMColor kZero = 0x00; - static const SkPMColor kHalf = 0x80; - static const SkPMColor k3Q = 0xC0; - static const SkPMColor kOne = 0xFF; - SkImageInfo info = SkImageInfo::MakeA8(width, height); - // The 4 byte alignment seems to be necessary to allow this bmp to be converted - // to an image. - result->allocPixels(info, SkAlign4(width)); +/** Helper to reuse above functions to produce images rather than bmps */ +static void bmp_to_image(TestPixels* result) { + SkASSERT(TestPixels::kBitmap == result->fType); + result->fImage.reset(SkImage::NewFromBitmap(result->fBitmap)); + SkASSERT(result->fImage); + result->fType = TestPixels::kImage; + result->fBitmap.reset(); +} + +/** Color image case. */ +bool make_ringed_color_image(GrContext* ctx, TestPixels* result, int width, int height) { + if (make_ringed_color_bitmap(ctx, result, width, height)) { + bmp_to_image(result); + return true; + } + return false; +} + +/** Alpha image case. */ +bool make_ringed_alpha_image(GrContext* ctx, TestPixels* result, int width, int height) { + if (make_ringed_alpha_bitmap(ctx, result, width, height)) { + bmp_to_image(result); + return true; + } + return false; +} + +/** Similar to make_ringed_bitmap with these modifications: + - The backing store is a texture. + - The texture is larger than the bitmap dimensions (it is surrounded by non-content + padding on the right/bottom of the contents.) + - The right/bottom sides of the rings are omitted so that the rect to draw is adjacent to + the texture padding. + */ +template <typename PIXEL_TYPE> +bool make_oversized_texture_bitmap(GrContext* ctx, TestPixels* result, int width, int height, + GrPixelConfig config, PIXEL_TYPE outerRingColor, + PIXEL_TYPE innerRingColor, PIXEL_TYPE checkColor1, + PIXEL_TYPE checkColor2, PIXEL_TYPE padColor) { + SkASSERT(0 == width % 2 && 0 == height % 2); + SkASSERT(width >= 6 && height >= 6); +#if SK_SUPPORT_GPU + if (!ctx) { + return false; + } + /** Put arbitrary pad to the right and below the bitmap content. */ + static const int kXPad = 10; + static const int kYPad = 17; + size_t rowBytes = (width + kXPad) * sizeof(PIXEL_TYPE); + SkAutoTMalloc<PIXEL_TYPE> pixels(rowBytes*(height + kYPad)); - uint8_t* scanline = result->getAddr8(0, 0); + PIXEL_TYPE* scanline = pixels.get(); for (int x = 0; x < width; ++x) { - scanline[x] = kOne; + scanline[x] = outerRingColor; } - scanline = result->getAddr8(0, 1); - scanline[0] = kOne; - for (int x = 1; x < width - 1; ++x) { - scanline[x] = kOne; + for (int x = width; x < width + kXPad; ++x) { + scanline[x] = padColor; } - scanline[width - 1] = kZero; - for (int y = 2; y < height / 2; ++y) { - scanline = result->getAddr8(0, y); - scanline[0] = kZero; - scanline[1] = kOne; - for (int x = 2; x < width / 2; ++x) { - scanline[x] = k3Q; + scanline = (PIXEL_TYPE*)((char*)scanline + rowBytes); + scanline[0] = outerRingColor; + for (int x = 1; x < width; ++x) { + scanline[x] = innerRingColor; + } + for (int x = width; x < width + kXPad; ++x) { + scanline[x] = padColor; + } + + for (int y = 2; y < height / 2 + 1; ++y) { + scanline = (PIXEL_TYPE*)((char*)scanline + rowBytes); + scanline[0] = outerRingColor; + scanline[1] = innerRingColor; + for (int x = 2; x < width / 2 + 1; ++x) { + scanline[x] = checkColor1; } - for (int x = width / 2; x < width - 2; ++x) { - scanline[x] = kHalf; + for (int x = width / 2 + 1; x < width; ++x) { + scanline[x] = checkColor2; + } + for (int x = width; x < width + kXPad; ++x) { + scanline[x] = padColor; } - scanline[width - 2] = kOne; - scanline[width - 1] = kZero; } - for (int y = height / 2; y < height - 2; ++y) { - scanline = result->getAddr8(0, y); - scanline[0] = kZero; - scanline[1] = kOne; - for (int x = 2; x < width / 2; ++x) { - scanline[x] = kHalf; + for (int y = height / 2 + 1; y < height; ++y) { + scanline = (PIXEL_TYPE*)((char*)scanline + rowBytes); + scanline[0] = outerRingColor; + scanline[1] = innerRingColor; + for (int x = 2; x < width / 2 + 1; ++x) { + scanline[x] = checkColor2; } - for (int x = width / 2; x < width - 2; ++x) { - scanline[x] = k3Q; + for (int x = width / 2 + 1; x < width; ++x) { + scanline[x] = checkColor1; + } + for (int x = width; x < width + kXPad; ++x) { + scanline[x] = padColor; } - scanline[width - 2] = kOne; - scanline[width - 1] = kZero; } - scanline = result->getAddr8(0, height - 2); - scanline[0] = kZero; - for (int x = 1; x < width - 1; ++x) { - scanline[x] = kOne; + for (int y = height; y < height + kYPad; ++y) { + scanline = (PIXEL_TYPE*)((char*)scanline + rowBytes); + for (int x = 0; x < width + kXPad; ++x) { + scanline[x] = padColor; + } } - scanline[width - 1] = kZero; - scanline = result->getAddr8(0, height - 1); - for (int x = 0; x < width; ++x) { - scanline[x] = kZero; + GrSurfaceDesc desc; + desc.fConfig = config; + desc.fWidth = width + kXPad; + desc.fHeight = height + kYPad; + SkAutoTUnref<GrTexture> texture(ctx->textureProvider()->createTexture(desc, true, pixels.get(), + rowBytes)); + + if (!texture) { + return false; } - result->setImmutable(); + + GrWrapTextureInBitmap(texture, width, height, true, &result->fBitmap); + result->fType = TestPixels::kBitmap; + result->fBitmap.setImmutable(); + result->fRect.set(2, 2, width, height); + return true; +#else + return false; +#endif +} + +/** Make the color version of the oversized texture-backed bitmap */ +static bool make_ringed_oversized_color_texture_bitmap(GrContext* ctx, TestPixels* result, + int width, int height) { + static const SkPMColor kBlue = SkPreMultiplyColor(SK_ColorBLUE); + static const SkPMColor kRed = SkPreMultiplyColor(SK_ColorRED); + static const SkPMColor kBlack = SkPreMultiplyColor(SK_ColorBLACK); + static const SkPMColor kWhite = SkPreMultiplyColor(SK_ColorWHITE); + static const SkPMColor kGreen = SkPreMultiplyColor(SK_ColorGREEN); + return make_oversized_texture_bitmap<SkPMColor>( + ctx, result, width, height, kSkia8888_GrPixelConfig, kBlue, kRed, kBlack, kWhite, kGreen); +} + +/** Make the alpha version of the oversized texture-backed bitmap */ +static bool make_ringed_oversized_alpha_texture_bitmap(GrContext* ctx, TestPixels* result, + int width, int height) { + static const uint8_t kZero = 0x00; + static const uint8_t kHalf = 0x80; + static const uint8_t k3Q = 0xC0; + static const uint8_t kOne = 0xFF; + static const uint8_t k1Q = 0x40; + return make_oversized_texture_bitmap<uint8_t>( + ctx, result, width, height, kAlpha_8_GrPixelConfig, kZero, kOne, k3Q, kHalf, k1Q); } static SkShader* make_shader() { @@ -234,26 +299,35 @@ enum BleedTest { const struct { const char* fName; - void(*fBmpMaker)(SkBitmap* result, int width, int height); - SkShader*(*fShaderMaker)(); - void(*fDraw)(SkCanvas*, const SkBitmap&, const SkImage*, const SkRect&, const SkRect&, - const SkPaint*, SkCanvas::SrcRectConstraint); + bool (*fPixelMaker)(GrContext*, TestPixels* result, int width, int height); + SkShader* (*fShaderMaker)(); } gBleedRec[] = { - { "bleed", make_ringed_color_bitmap, make_null_shader, draw_bitmap_rect }, - { "bleed_texture_bmp", make_ringed_color_bitmap, make_null_shader, draw_texture_bitmap_rect }, - { "bleed_image", make_ringed_color_bitmap, make_null_shader, draw_image_rect }, - { "bleed_alpha_bmp", make_ringed_alpha_bitmap, make_null_shader, draw_bitmap_rect }, - { "bleed_alpha_texture_bmp", make_ringed_alpha_bitmap, make_null_shader, draw_texture_bitmap_rect }, - { "bleed_alpha_image", make_ringed_alpha_bitmap, make_null_shader, draw_image_rect }, - { "bleed_alpha_bmp_shader", make_ringed_alpha_bitmap, make_shader, draw_bitmap_rect }, - { "bleed_alpha_texture_bmp_shader", make_ringed_alpha_bitmap, make_shader, draw_texture_bitmap_rect }, - { "bleed_alpha_image_shader", make_ringed_alpha_bitmap, make_shader, draw_image_rect }, + { "bleed", make_ringed_color_bitmap, make_null_shader }, + { "bleed_texture_bmp", make_ringed_oversized_color_texture_bitmap, make_null_shader }, + { "bleed_image", make_ringed_color_image, make_null_shader }, + { "bleed_alpha_bmp", make_ringed_alpha_bitmap, make_null_shader }, + { "bleed_alpha_texture_bmp", make_ringed_oversized_alpha_texture_bitmap, make_null_shader }, + { "bleed_alpha_image", make_ringed_alpha_image, make_null_shader }, + { "bleed_alpha_bmp_shader", make_ringed_alpha_bitmap, make_shader }, + { "bleed_alpha_texture_bmp_shader", make_ringed_oversized_alpha_texture_bitmap, make_shader }, + { "bleed_alpha_image_shader", make_ringed_alpha_image, make_shader }, }; -// This GM exercises the drawBitmapRect constraints +/** This GM exercises the behavior of the drawBitmapRect & drawImageRect calls. Specifically their + handling of : + - SrcRectConstraint(bleed vs.no - bleed) + - handling of the sub - region feature(area - of - interest) of drawBitmap* + - handling of 8888 vs. A8 (including presence of a shader in the A8 case). + - (gpu - only) handling of tiled vs.non - tiled drawing) + - (gpu - only) texture's backing a bmp where the texture is larger than the bmp. + In particular, we should never see the padding outside of an SkBitmap's sub - region (green for + 8888, 1/4 for alpha). In some instances we can see the two outer rings outside of the area o + interest (i.e., the inner four checks) due to AA or filtering if allowed by the + SrcRectConstraint. +*/ class BleedGM : public skiagm::GM { public: - BleedGM(BleedTest bt) : fBT(bt) {} + BleedGM(BleedTest bt) : fCreatedPixels(false), fBT(bt){} protected: @@ -265,24 +339,21 @@ protected: return SkISize::Make(1200, 1080); } - void onOnceBeforeDraw() override { - gBleedRec[fBT].fBmpMaker(&fBitmapSmall, kSmallTextureSize, kSmallTextureSize); - fImageSmall.reset(SkImage::NewFromBitmap(fBitmapSmall)); - - // To exercise the GPU's tiling path we need a texture - // too big for the GPU to handle in one go - gBleedRec[fBT].fBmpMaker(&fBitmapBig, 2*kMaxTileSize, 2*kMaxTileSize); - fImageBig.reset(SkImage::NewFromBitmap(fBitmapBig)); - - fShader.reset(gBleedRec[fBT].fShaderMaker()); + void drawPixels(SkCanvas* canvas, const TestPixels& pixels, const SkRect& src, + const SkRect& dst, const SkPaint* paint, + SkCanvas::SrcRectConstraint constraint) { + if (TestPixels::kBitmap == pixels.fType) { + canvas->drawBitmapRect(pixels.fBitmap, src, dst, paint, constraint); + } else { + canvas->drawImageRect(pixels.fImage, src, dst, paint, constraint); + } } - // Draw only the center of the small bitmap + // Draw the area of interest of the small image void drawCase1(SkCanvas* canvas, int transX, int transY, bool aa, SkCanvas::SrcRectConstraint constraint, SkFilterQuality filter) { - SkRect src = SkRect::MakeXYWH(2, 2, - SkIntToScalar(kSmallTextureSize-4), - SkIntToScalar(kSmallTextureSize-4)); + + SkRect src = SkRect::Make(fSmallTestPixels.fRect); SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY), SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize)); @@ -292,15 +363,13 @@ protected: paint.setColor(SK_ColorBLUE); paint.setAntiAlias(aa); - gBleedRec[fBT].fDraw(canvas, fBitmapSmall, fImageSmall, src, dst, &paint, constraint); + this->drawPixels(canvas, fSmallTestPixels, src, dst, &paint, constraint); } - // Draw almost all of the large bitmap + // Draw the area of interest of the large image void drawCase2(SkCanvas* canvas, int transX, int transY, bool aa, SkCanvas::SrcRectConstraint constraint, SkFilterQuality filter) { - SkRect src = SkRect::MakeXYWH(2, 2, - SkIntToScalar(fBitmapBig.width()-4), - SkIntToScalar(fBitmapBig.height()-4)); + SkRect src = SkRect::Make(fBigTestPixels.fRect); SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY), SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize)); @@ -310,15 +379,16 @@ protected: paint.setColor(SK_ColorBLUE); paint.setAntiAlias(aa); - gBleedRec[fBT].fDraw(canvas, fBitmapBig, fImageBig, src, dst, &paint, constraint); + this->drawPixels(canvas, fBigTestPixels, src, dst, &paint, constraint); } - // Draw ~1/4 of the large bitmap + // Draw upper-left 1/4 of the area of interest of the large image void drawCase3(SkCanvas* canvas, int transX, int transY, bool aa, SkCanvas::SrcRectConstraint constraint, SkFilterQuality filter) { - SkRect src = SkRect::MakeXYWH(2, 2, - SkIntToScalar(fBitmapBig.width()/2-2), - SkIntToScalar(fBitmapBig.height()/2-2)); + SkRect src = SkRect::MakeXYWH(SkIntToScalar(fBigTestPixels.fRect.fLeft), + SkIntToScalar(fBigTestPixels.fRect.fTop), + fBigTestPixels.fRect.width()/2.f, + fBigTestPixels.fRect.height()/2.f); SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY), SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize)); @@ -328,15 +398,13 @@ protected: paint.setColor(SK_ColorBLUE); paint.setAntiAlias(aa); - gBleedRec[fBT].fDraw(canvas, fBitmapBig, fImageBig, src, dst, &paint, constraint); + this->drawPixels(canvas, fBigTestPixels, src, dst, &paint, constraint); } - // Draw the center of the small bitmap with a normal blur + // Draw the area of interest of the small image with a normal blur void drawCase4(SkCanvas* canvas, int transX, int transY, bool aa, SkCanvas::SrcRectConstraint constraint, SkFilterQuality filter) { - SkRect src = SkRect::MakeXYWH(2, 2, - SkIntToScalar(kSmallTextureSize-4), - SkIntToScalar(kSmallTextureSize-4)); + SkRect src = SkRect::Make(fSmallTestPixels.fRect); SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY), SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize)); @@ -349,15 +417,13 @@ protected: paint.setColor(SK_ColorBLUE); paint.setAntiAlias(aa); - gBleedRec[fBT].fDraw(canvas, fBitmapSmall, fImageSmall, src, dst, &paint, constraint); + this->drawPixels(canvas, fSmallTestPixels, src, dst, &paint, constraint); } - // Draw the center of the small bitmap with a outer blur + // Draw the area of interest of the small image with a outer blur void drawCase5(SkCanvas* canvas, int transX, int transY, bool aa, SkCanvas::SrcRectConstraint constraint, SkFilterQuality filter) { - SkRect src = SkRect::MakeXYWH(2, 2, - SkIntToScalar(kSmallTextureSize - 4), - SkIntToScalar(kSmallTextureSize - 4)); + SkRect src = SkRect::Make(fSmallTestPixels.fRect); SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY), SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize)); @@ -370,10 +436,40 @@ protected: paint.setColor(SK_ColorBLUE); paint.setAntiAlias(aa); - gBleedRec[fBT].fDraw(canvas, fBitmapSmall, fImageSmall, src, dst, &paint, constraint); + this->drawPixels(canvas, fSmallTestPixels, src, dst, &paint, constraint); } void onDraw(SkCanvas* canvas) override { + // We don't create pixels in an onOnceBeforeDraw() override because we want access to + // GrContext. + GrContext* context = canvas->getGrContext(); +#if SK_SUPPORT_GPU + // Workaround for SampleApp. + if (GrTexture* tex = fBigTestPixels.fBitmap.getTexture()) { + if (tex->wasDestroyed()) { + fCreatedPixels = false; + } + } +#endif + bool madePixels = fCreatedPixels; + + if (!madePixels) { + madePixels = gBleedRec[fBT].fPixelMaker(context, &fSmallTestPixels, kSmallTextureSize, + kSmallTextureSize); + madePixels &= gBleedRec[fBT].fPixelMaker(context, &fBigTestPixels, 2 * kMaxTileSize, + 2 * kMaxTileSize); + fCreatedPixels = madePixels; + } + + // Assume that if we coulnd't make the bitmap/image it's because it's a GPU test on a + // non-GPU backend. + if (!madePixels) { + skiagm::GM::DrawGpuOnlyMessage(canvas); + return; + } + + fShader.reset(gBleedRec[fBT].fShaderMaker()); + canvas->clear(SK_ColorGRAY); SkTDArray<SkMatrix> matrices; // Draw with identity @@ -486,14 +582,13 @@ private: static const int kSmallTextureSize = 6; static const int kMaxTileSize = 32; - SkBitmap fBitmapSmall; - SkBitmap fBitmapBig; - SkAutoTUnref<SkImage> fImageSmall; - SkAutoTUnref<SkImage> fImageBig; + bool fCreatedPixels; + TestPixels fBigTestPixels; + TestPixels fSmallTestPixels; - SkAutoTUnref<SkShader> fShader; + SkAutoTUnref<SkShader> fShader; - const BleedTest fBT; + const BleedTest fBT; typedef GM INHERITED; }; |