| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2011 Google Inc. | 
 | 3 |  * | 
 | 4 |  * Use of this source code is governed by a BSD-style license that can be | 
 | 5 |  * found in the LICENSE file. | 
 | 6 |  */ | 
 | 7 |  | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 8 | #include "SkCanvas.h" | 
| bsalomon@google.com | cf8fb1f | 2012-08-02 14:03:32 +0000 | [diff] [blame] | 9 | #include "SkColorPriv.h" | 
| reed@google.com | 4b163ed | 2012-08-07 21:35:13 +0000 | [diff] [blame] | 10 | #include "SkMathPriv.h" | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 11 | #include "SkRegion.h" | 
| reed | 52d9ac6 | 2014-06-30 09:05:34 -0700 | [diff] [blame] | 12 | #include "SkSurface.h" | 
| tfarina@chromium.org | 4ee16bf | 2014-01-10 22:08:27 +0000 | [diff] [blame] | 13 | #include "Test.h" | 
| tfarina@chromium.org | 4ee16bf | 2014-01-10 22:08:27 +0000 | [diff] [blame] | 14 |  | 
| bsalomon@google.com | cf8fb1f | 2012-08-02 14:03:32 +0000 | [diff] [blame] | 15 | #if SK_SUPPORT_GPU | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 16 | #include "GrContext.h" | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 17 | #include "SkGr.h" | 
| bsalomon@google.com | cf8fb1f | 2012-08-02 14:03:32 +0000 | [diff] [blame] | 18 | #endif | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 19 |  | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 20 | #include <initializer_list> | 
 | 21 |  | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 22 | static const int DEV_W = 100, DEV_H = 100; | 
 | 23 | static const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H); | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame] | 24 | static const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1, | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 25 |                                                 DEV_H * SK_Scalar1); | 
 | 26 |  | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 27 | static SkPMColor get_src_color(int x, int y) { | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 28 |     SkASSERT(x >= 0 && x < DEV_W); | 
 | 29 |     SkASSERT(y >= 0 && y < DEV_H); | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 30 |  | 
 | 31 |     U8CPU r = x; | 
 | 32 |     U8CPU g = y; | 
 | 33 |     U8CPU b = 0xc; | 
 | 34 |  | 
 | 35 |     U8CPU a = 0xff; | 
| bsalomon@google.com | c436499 | 2011-11-07 15:54:49 +0000 | [diff] [blame] | 36 |     switch ((x+y) % 5) { | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 37 |         case 0: | 
 | 38 |             a = 0xff; | 
 | 39 |             break; | 
 | 40 |         case 1: | 
 | 41 |             a = 0x80; | 
 | 42 |             break; | 
 | 43 |         case 2: | 
 | 44 |             a = 0xCC; | 
 | 45 |             break; | 
 | 46 |         case 4: | 
 | 47 |             a = 0x01; | 
 | 48 |             break; | 
 | 49 |         case 3: | 
 | 50 |             a = 0x00; | 
 | 51 |             break; | 
 | 52 |     } | 
 | 53 |     return SkPremultiplyARGBInline(a, r, g, b); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 54 | } | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 55 |      | 
 | 56 | static SkPMColor get_dst_bmp_init_color(int x, int y, int w) { | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 57 |     int n = y * w + x; | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 58 |  | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 59 |     U8CPU b = n & 0xff; | 
 | 60 |     U8CPU g = (n >> 8) & 0xff; | 
 | 61 |     U8CPU r = (n >> 16) & 0xff; | 
 | 62 |     return SkPackARGB32(0xff, r, g , b); | 
 | 63 | } | 
 | 64 |  | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 65 | static SkPMColor convert_to_pmcolor(SkColorType ct, SkAlphaType at, const uint32_t* addr, | 
 | 66 |                                     bool* doUnpremul) { | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 67 |     *doUnpremul = (kUnpremul_SkAlphaType == at); | 
 | 68 |  | 
 | 69 |     const uint8_t* c = reinterpret_cast<const uint8_t*>(addr); | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 70 |     U8CPU a,r,g,b; | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 71 |     switch (ct) { | 
 | 72 |         case kBGRA_8888_SkColorType: | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 73 |             b = static_cast<U8CPU>(c[0]); | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 74 |             g = static_cast<U8CPU>(c[1]); | 
 | 75 |             r = static_cast<U8CPU>(c[2]); | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 76 |             a = static_cast<U8CPU>(c[3]); | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 77 |             break; | 
 | 78 |         case kRGBA_8888_SkColorType: | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 79 |             r = static_cast<U8CPU>(c[0]); | 
 | 80 |             g = static_cast<U8CPU>(c[1]); | 
 | 81 |             b = static_cast<U8CPU>(c[2]); | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 82 |             a = static_cast<U8CPU>(c[3]); | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 83 |             break; | 
| bsalomon@google.com | ccaa002 | 2012-09-25 19:55:07 +0000 | [diff] [blame] | 84 |         default: | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 85 |             SkDEBUGFAIL("Unexpected colortype"); | 
| bsalomon@google.com | ccaa002 | 2012-09-25 19:55:07 +0000 | [diff] [blame] | 86 |             return 0; | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 87 |     } | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 88 |  | 
 | 89 |     if (*doUnpremul) { | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 90 |         r = SkMulDiv255Ceiling(r, a); | 
 | 91 |         g = SkMulDiv255Ceiling(g, a); | 
 | 92 |         b = SkMulDiv255Ceiling(b, a); | 
 | 93 |     } | 
 | 94 |     return SkPackARGB32(a, r, g, b); | 
 | 95 | } | 
 | 96 |  | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 97 | static SkBitmap make_src_bitmap() { | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 98 |     static SkBitmap bmp; | 
 | 99 |     if (bmp.isNull()) { | 
| reed | 8482504 | 2014-09-02 12:50:45 -0700 | [diff] [blame] | 100 |         bmp.allocN32Pixels(DEV_W, DEV_H); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 101 |         intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels()); | 
 | 102 |         for (int y = 0; y < DEV_H; ++y) { | 
 | 103 |             for (int x = 0; x < DEV_W; ++x) { | 
 | 104 |                 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel()); | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 105 |                 *pixel = get_src_color(x, y); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 106 |             } | 
 | 107 |         } | 
 | 108 |     } | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 109 |     return bmp; | 
 | 110 | } | 
 | 111 |  | 
 | 112 | static void fill_src_canvas(SkCanvas* canvas) { | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 113 |     canvas->save(); | 
 | 114 |     canvas->setMatrix(SkMatrix::I()); | 
 | 115 |     canvas->clipRect(DEV_RECT_S, SkRegion::kReplace_Op); | 
 | 116 |     SkPaint paint; | 
 | 117 |     paint.setXfermodeMode(SkXfermode::kSrc_Mode); | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 118 |     canvas->drawBitmap(make_src_bitmap(), 0, 0, &paint); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 119 |     canvas->restore(); | 
 | 120 | } | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame] | 121 |  | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 122 | #if SK_SUPPORT_GPU | 
 | 123 | static void fill_src_texture(GrTexture* texture) { | 
 | 124 |     SkBitmap bmp = make_src_bitmap(); | 
 | 125 |     bmp.lockPixels(); | 
 | 126 |     texture->writePixels(0, 0, DEV_W, DEV_H, kSkia8888_GrPixelConfig, bmp.getPixels(), | 
 | 127 |                          bmp.rowBytes()); | 
 | 128 |     bmp.unlockPixels(); | 
 | 129 | } | 
 | 130 | #endif | 
 | 131 |  | 
 | 132 | static void fill_dst_bmp_with_init_data(SkBitmap* bitmap) { | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 133 |     SkASSERT(bitmap->lockPixelsAreWritable()); | 
 | 134 |     SkAutoLockPixels alp(*bitmap); | 
 | 135 |     int w = bitmap->width(); | 
 | 136 |     int h = bitmap->height(); | 
 | 137 |     intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels()); | 
 | 138 |     for (int y = 0; y < h; ++y) { | 
 | 139 |         for (int x = 0; x < w; ++x) { | 
 | 140 |             SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel()); | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 141 |             *pixel = get_dst_bmp_init_color(x, y, w); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 142 |         } | 
 | 143 |     } | 
 | 144 | } | 
 | 145 |  | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 146 | static bool check_read_pixel(SkPMColor a, SkPMColor b, bool didPremulConversion) { | 
| bsalomon@google.com | c436499 | 2011-11-07 15:54:49 +0000 | [diff] [blame] | 147 |     if (!didPremulConversion) { | 
 | 148 |         return a == b; | 
 | 149 |     } | 
 | 150 |     int32_t aA = static_cast<int32_t>(SkGetPackedA32(a)); | 
 | 151 |     int32_t aR = static_cast<int32_t>(SkGetPackedR32(a)); | 
 | 152 |     int32_t aG = static_cast<int32_t>(SkGetPackedG32(a)); | 
 | 153 |     int32_t aB = SkGetPackedB32(a); | 
 | 154 |  | 
 | 155 |     int32_t bA = static_cast<int32_t>(SkGetPackedA32(b)); | 
 | 156 |     int32_t bR = static_cast<int32_t>(SkGetPackedR32(b)); | 
 | 157 |     int32_t bG = static_cast<int32_t>(SkGetPackedG32(b)); | 
 | 158 |     int32_t bB = static_cast<int32_t>(SkGetPackedB32(b)); | 
 | 159 |  | 
 | 160 |     return aA == bA && | 
 | 161 |            SkAbs32(aR - bR) <= 1 && | 
 | 162 |            SkAbs32(aG - bG) <= 1 && | 
 | 163 |            SkAbs32(aB - bB) <= 1; | 
 | 164 | } | 
 | 165 |  | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 166 | // checks the bitmap contains correct pixels after the readPixels | 
 | 167 | // if the bitmap was prefilled with pixels it checks that these weren't | 
 | 168 | // overwritten in the area outside the readPixels. | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 169 | static bool check_read(skiatest::Reporter* reporter, | 
 | 170 |                        const SkBitmap& bitmap, | 
 | 171 |                        int x, int y, | 
 | 172 |                        bool checkCanvasPixels, | 
 | 173 |                        bool checkBitmapPixels) { | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 174 |     SkASSERT(4 == bitmap.bytesPerPixel()); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 175 |     SkASSERT(!bitmap.isNull()); | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 176 |     SkASSERT(checkCanvasPixels || checkBitmapPixels); | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame] | 177 |  | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 178 |     const SkColorType ct = bitmap.colorType(); | 
 | 179 |     const SkAlphaType at = bitmap.alphaType(); | 
 | 180 |  | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 181 |     int bw = bitmap.width(); | 
 | 182 |     int bh = bitmap.height(); | 
 | 183 |  | 
 | 184 |     SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh); | 
 | 185 |     SkIRect clippedSrcRect = DEV_RECT; | 
 | 186 |     if (!clippedSrcRect.intersect(srcRect)) { | 
 | 187 |         clippedSrcRect.setEmpty(); | 
 | 188 |     } | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 189 |     SkAutoLockPixels alp(bitmap); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 190 |     for (int by = 0; by < bh; ++by) { | 
 | 191 |         for (int bx = 0; bx < bw; ++bx) { | 
 | 192 |             int devx = bx + srcRect.fLeft; | 
 | 193 |             int devy = by + srcRect.fTop; | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame] | 194 |  | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 195 |             const uint32_t* pixel = bitmap.getAddr32(bx, by); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 196 |  | 
 | 197 |             if (clippedSrcRect.contains(devx, devy)) { | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 198 |                 if (checkCanvasPixels) { | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 199 |                     SkPMColor canvasPixel = get_src_color(devx, devy); | 
| bsalomon@google.com | c436499 | 2011-11-07 15:54:49 +0000 | [diff] [blame] | 200 |                     bool didPremul; | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 201 |                     SkPMColor pmPixel = convert_to_pmcolor(ct, at, pixel, &didPremul); | 
| bsalomon | 3982602 | 2015-07-23 08:07:21 -0700 | [diff] [blame] | 202 |                     if (!check_read_pixel(pmPixel, canvasPixel, didPremul)) { | 
 | 203 |                         ERRORF(reporter, "Expected readback pixel value 0x%08x, got 0x%08x. " | 
 | 204 |                                "Readback was unpremul: %d", canvasPixel, pmPixel, didPremul); | 
| bsalomon@google.com | 72f3dca | 2012-08-17 13:32:06 +0000 | [diff] [blame] | 205 |                         return false; | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 206 |                     } | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 207 |                 } | 
| bsalomon@google.com | 6850eab | 2011-11-03 20:29:47 +0000 | [diff] [blame] | 208 |             } else if (checkBitmapPixels) { | 
| bsalomon | 3982602 | 2015-07-23 08:07:21 -0700 | [diff] [blame] | 209 |                 uint32_t origDstPixel = get_dst_bmp_init_color(bx, by, bw); | 
 | 210 |                 if (origDstPixel != *pixel) { | 
 | 211 |                     ERRORF(reporter, "Expected clipped out area of readback to be unchanged. " | 
 | 212 |                            "Expected 0x%08x, got 0x%08x", origDstPixel, *pixel); | 
| bsalomon@google.com | 72f3dca | 2012-08-17 13:32:06 +0000 | [diff] [blame] | 213 |                     return false; | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 214 |                 } | 
 | 215 |             } | 
 | 216 |         } | 
 | 217 |     } | 
| bsalomon@google.com | 72f3dca | 2012-08-17 13:32:06 +0000 | [diff] [blame] | 218 |     return true; | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 219 | } | 
 | 220 |  | 
 | 221 | enum BitmapInit { | 
 | 222 |     kFirstBitmapInit = 0, | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame] | 223 |  | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 224 |     kNoPixels_BitmapInit = kFirstBitmapInit, | 
 | 225 |     kTight_BitmapInit, | 
 | 226 |     kRowBytes_BitmapInit, | 
| bsalomon | 9d02b26 | 2016-02-01 12:49:30 -0800 | [diff] [blame^] | 227 |     kRowBytesOdd_BitmapInit, | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame] | 228 |  | 
| bsalomon | 9d02b26 | 2016-02-01 12:49:30 -0800 | [diff] [blame^] | 229 |     kLastAligned_BitmapInit = kRowBytes_BitmapInit, | 
 | 230 |     kLast_BitmapInit = kRowBytesOdd_BitmapInit | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 231 | }; | 
 | 232 |  | 
| commit-bot@chromium.org | ddf94cf | 2013-10-12 17:25:17 +0000 | [diff] [blame] | 233 | static BitmapInit nextBMI(BitmapInit bmi) { | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 234 |     int x = bmi; | 
 | 235 |     return static_cast<BitmapInit>(++x); | 
 | 236 | } | 
 | 237 |  | 
| commit-bot@chromium.org | a713f9c | 2014-03-17 21:31:26 +0000 | [diff] [blame] | 238 | static void init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init, SkColorType ct, | 
 | 239 |                         SkAlphaType at) { | 
 | 240 |     SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), ct, at); | 
| commit-bot@chromium.org | fa9e5fa | 2014-02-13 22:00:04 +0000 | [diff] [blame] | 241 |     size_t rowBytes = 0; | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 242 |     bool alloc = true; | 
 | 243 |     switch (init) { | 
 | 244 |         case kNoPixels_BitmapInit: | 
 | 245 |             alloc = false; | 
 | 246 |         case kTight_BitmapInit: | 
 | 247 |             break; | 
 | 248 |         case kRowBytes_BitmapInit: | 
| commit-bot@chromium.org | fa9e5fa | 2014-02-13 22:00:04 +0000 | [diff] [blame] | 249 |             rowBytes = (info.width() + 16) * sizeof(SkPMColor); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 250 |             break; | 
| bsalomon | 9d02b26 | 2016-02-01 12:49:30 -0800 | [diff] [blame^] | 251 |         case kRowBytesOdd_BitmapInit: | 
 | 252 |             rowBytes = (info.width() * sizeof(SkPMColor)) + 3; | 
 | 253 |             break; | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 254 |         default: | 
 | 255 |             SkASSERT(0); | 
 | 256 |             break; | 
 | 257 |     } | 
| skia.committer@gmail.com | 02d6f54 | 2014-02-14 03:02:05 +0000 | [diff] [blame] | 258 |  | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 259 |     if (alloc) { | 
| bsalomon | 9d02b26 | 2016-02-01 12:49:30 -0800 | [diff] [blame^] | 260 |         bitmap->allocPixels(info, rowBytes); | 
| commit-bot@chromium.org | fa9e5fa | 2014-02-13 22:00:04 +0000 | [diff] [blame] | 261 |     } else { | 
| commit-bot@chromium.org | a3264e5 | 2014-05-30 13:26:10 +0000 | [diff] [blame] | 262 |         bitmap->setInfo(info, rowBytes); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 263 |     } | 
 | 264 | } | 
 | 265 |  | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 266 | static const struct { | 
 | 267 |     SkColorType fColorType; | 
 | 268 |     SkAlphaType fAlphaType; | 
 | 269 | } gReadPixelsConfigs[] = { | 
 | 270 |     { kRGBA_8888_SkColorType,   kPremul_SkAlphaType }, | 
 | 271 |     { kRGBA_8888_SkColorType,   kUnpremul_SkAlphaType }, | 
 | 272 |     { kBGRA_8888_SkColorType,   kPremul_SkAlphaType }, | 
 | 273 |     { kBGRA_8888_SkColorType,   kUnpremul_SkAlphaType }, | 
 | 274 | }; | 
 | 275 | const SkIRect gReadPixelsTestRects[] = { | 
 | 276 |     // entire thing | 
 | 277 |     DEV_RECT, | 
 | 278 |     // larger on all sides | 
 | 279 |     SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10), | 
 | 280 |     // fully contained | 
 | 281 |     SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4), | 
 | 282 |     // outside top left | 
 | 283 |     SkIRect::MakeLTRB(-10, -10, -1, -1), | 
 | 284 |     // touching top left corner | 
 | 285 |     SkIRect::MakeLTRB(-10, -10, 0, 0), | 
 | 286 |     // overlapping top left corner | 
 | 287 |     SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H / 4), | 
 | 288 |     // overlapping top left and top right corners | 
 | 289 |     SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, DEV_H / 4), | 
 | 290 |     // touching entire top edge | 
 | 291 |     SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, 0), | 
 | 292 |     // overlapping top right corner | 
 | 293 |     SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W  + 10, DEV_H / 4), | 
 | 294 |     // contained in x, overlapping top edge | 
 | 295 |     SkIRect::MakeLTRB(DEV_W / 4, -10, 3 * DEV_W  / 4, DEV_H / 4), | 
 | 296 |     // outside top right corner | 
 | 297 |     SkIRect::MakeLTRB(DEV_W + 1, -10, DEV_W + 10, -1), | 
 | 298 |     // touching top right corner | 
 | 299 |     SkIRect::MakeLTRB(DEV_W, -10, DEV_W + 10, 0), | 
 | 300 |     // overlapping top left and bottom left corners | 
 | 301 |     SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H + 10), | 
 | 302 |     // touching entire left edge | 
 | 303 |     SkIRect::MakeLTRB(-10, -10, 0, DEV_H + 10), | 
 | 304 |     // overlapping bottom left corner | 
 | 305 |     SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W / 4, DEV_H + 10), | 
 | 306 |     // contained in y, overlapping left edge | 
 | 307 |     SkIRect::MakeLTRB(-10, DEV_H / 4, DEV_W / 4, 3 * DEV_H / 4), | 
 | 308 |     // outside bottom left corner | 
 | 309 |     SkIRect::MakeLTRB(-10, DEV_H + 1, -1, DEV_H + 10), | 
 | 310 |     // touching bottom left corner | 
 | 311 |     SkIRect::MakeLTRB(-10, DEV_H, 0, DEV_H + 10), | 
 | 312 |     // overlapping bottom left and bottom right corners | 
 | 313 |     SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10), | 
 | 314 |     // touching entire left edge | 
 | 315 |     SkIRect::MakeLTRB(0, DEV_H, DEV_W, DEV_H + 10), | 
 | 316 |     // overlapping bottom right corner | 
 | 317 |     SkIRect::MakeLTRB(3 * DEV_W / 4, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10), | 
 | 318 |     // overlapping top right and bottom right corners | 
 | 319 |     SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H + 10), | 
 | 320 | }; | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 321 |  | 
| bsalomon | 9d02b26 | 2016-02-01 12:49:30 -0800 | [diff] [blame^] | 322 | static void test_readpixels(skiatest::Reporter* reporter, SkSurface* surface, | 
 | 323 |                             BitmapInit lastBitmapInit) { | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 324 |     SkCanvas* canvas = surface->getCanvas(); | 
 | 325 |     fill_src_canvas(canvas); | 
 | 326 |     for (size_t rect = 0; rect < SK_ARRAY_COUNT(gReadPixelsTestRects); ++rect) { | 
 | 327 |         const SkIRect& srcRect = gReadPixelsTestRects[rect]; | 
| bsalomon | 9d02b26 | 2016-02-01 12:49:30 -0800 | [diff] [blame^] | 328 |         for (BitmapInit bmi = kFirstBitmapInit; bmi <= lastBitmapInit; bmi = nextBMI(bmi)) { | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 329 |             for (size_t c = 0; c < SK_ARRAY_COUNT(gReadPixelsConfigs); ++c) { | 
 | 330 |                 SkBitmap bmp; | 
 | 331 |                 init_bitmap(&bmp, srcRect, bmi, | 
 | 332 |                             gReadPixelsConfigs[c].fColorType, gReadPixelsConfigs[c].fAlphaType); | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 333 |  | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 334 |                 // if the bitmap has pixels allocated before the readPixels, | 
 | 335 |                 // note that and fill them with pattern | 
 | 336 |                 bool startsWithPixels = !bmp.isNull(); | 
 | 337 |                 if (startsWithPixels) { | 
 | 338 |                     fill_dst_bmp_with_init_data(&bmp); | 
 | 339 |                 } | 
 | 340 |                 uint32_t idBefore = surface->generationID(); | 
 | 341 |                 bool success = canvas->readPixels(&bmp, srcRect.fLeft, srcRect.fTop); | 
 | 342 |                 uint32_t idAfter = surface->generationID(); | 
 | 343 |  | 
 | 344 |                 // we expect to succeed when the read isn't fully clipped | 
 | 345 |                 // out. | 
 | 346 |                 bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RECT); | 
 | 347 |                 // determine whether we expected the read to succeed. | 
 | 348 |                 REPORTER_ASSERT(reporter, success == expectSuccess); | 
 | 349 |                 // read pixels should never change the gen id | 
 | 350 |                 REPORTER_ASSERT(reporter, idBefore == idAfter); | 
 | 351 |  | 
 | 352 |                 if (success || startsWithPixels) { | 
 | 353 |                     check_read(reporter, bmp, srcRect.fLeft, srcRect.fTop, | 
 | 354 |                                success, startsWithPixels); | 
 | 355 |                 } else { | 
 | 356 |                     // if we had no pixels beforehand and the readPixels | 
 | 357 |                     // failed then our bitmap should still not have pixels | 
 | 358 |                     REPORTER_ASSERT(reporter, bmp.isNull()); | 
 | 359 |                 } | 
 | 360 |             } | 
 | 361 |             // check the old webkit version of readPixels that clips the | 
 | 362 |             // bitmap size | 
 | 363 |             SkBitmap wkbmp; | 
 | 364 |             bool success = canvas->readPixels(srcRect, &wkbmp); | 
 | 365 |             SkIRect clippedRect = DEV_RECT; | 
 | 366 |             if (clippedRect.intersect(srcRect)) { | 
 | 367 |                 REPORTER_ASSERT(reporter, success); | 
 | 368 |                 REPORTER_ASSERT(reporter, kN32_SkColorType == wkbmp.colorType()); | 
 | 369 |                 REPORTER_ASSERT(reporter, kPremul_SkAlphaType == wkbmp.alphaType()); | 
 | 370 |                 check_read(reporter, wkbmp, clippedRect.fLeft, | 
 | 371 |                            clippedRect.fTop, true, false); | 
| bsalomon@google.com | 67b915d | 2013-02-04 16:13:32 +0000 | [diff] [blame] | 372 |             } else { | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 373 |                 REPORTER_ASSERT(reporter, !success); | 
| bsalomon@google.com | 67b915d | 2013-02-04 16:13:32 +0000 | [diff] [blame] | 374 |             } | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 375 |         } | 
 | 376 |     } | 
 | 377 | } | 
 | 378 | DEF_TEST(ReadPixels, reporter) { | 
 | 379 |     const SkImageInfo info = SkImageInfo::MakeN32Premul(DEV_W, DEV_H); | 
 | 380 |     SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info)); | 
| bsalomon | 9d02b26 | 2016-02-01 12:49:30 -0800 | [diff] [blame^] | 381 |     // SW readback fails a premul check when reading back to an unaligned rowbytes. | 
 | 382 |     test_readpixels(reporter, surface, kLastAligned_BitmapInit); | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 383 | } | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 384 | #if SK_SUPPORT_GPU | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 385 | DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadPixels_Gpu, reporter, context) { | 
 | 386 |     for (auto& origin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin}) { | 
 | 387 |         GrSurfaceDesc desc; | 
 | 388 |         desc.fFlags = kRenderTarget_GrSurfaceFlag; | 
 | 389 |         desc.fWidth = DEV_W; | 
 | 390 |         desc.fHeight = DEV_H; | 
 | 391 |         desc.fConfig = kSkia8888_GrPixelConfig; | 
 | 392 |         desc.fOrigin = origin; | 
 | 393 |         SkAutoTUnref<GrTexture> surfaceTexture( | 
 | 394 |             context->textureProvider()->createTexture(desc, false)); | 
 | 395 |         SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(surfaceTexture->asRenderTarget())); | 
 | 396 |         desc.fFlags = kNone_GrSurfaceFlags; | 
| bsalomon | 9d02b26 | 2016-02-01 12:49:30 -0800 | [diff] [blame^] | 397 |         test_readpixels(reporter, surface, kLast_BitmapInit); | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 398 |     } | 
 | 399 | } | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 400 | #endif | 
| bsalomon@google.com | 67b915d | 2013-02-04 16:13:32 +0000 | [diff] [blame] | 401 |  | 
| bsalomon | e8d21e8 | 2015-07-16 08:23:13 -0700 | [diff] [blame] | 402 | #if SK_SUPPORT_GPU | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 403 | static void test_readpixels_texture(skiatest::Reporter* reporter, GrTexture* texture) { | 
 | 404 |     fill_src_texture(texture); | 
 | 405 |     for (size_t rect = 0; rect < SK_ARRAY_COUNT(gReadPixelsTestRects); ++rect) { | 
 | 406 |         const SkIRect& srcRect = gReadPixelsTestRects[rect]; | 
| bsalomon | 9d02b26 | 2016-02-01 12:49:30 -0800 | [diff] [blame^] | 407 |         for (BitmapInit bmi = kFirstBitmapInit; bmi <= kLast_BitmapInit; bmi = nextBMI(bmi)) { | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 408 |             for (size_t c = 0; c < SK_ARRAY_COUNT(gReadPixelsConfigs); ++c) { | 
 | 409 |                 SkBitmap bmp; | 
 | 410 |                 init_bitmap(&bmp, srcRect, bmi, | 
 | 411 |                             gReadPixelsConfigs[c].fColorType, gReadPixelsConfigs[c].fAlphaType); | 
 | 412 |  | 
 | 413 |                 // if the bitmap has pixels allocated before the readPixels, | 
 | 414 |                 // note that and fill them with pattern | 
 | 415 |                 bool startsWithPixels = !bmp.isNull(); | 
 | 416 |                 // Try doing the read directly from a non-renderable texture | 
 | 417 |                 if (startsWithPixels) { | 
 | 418 |                     fill_dst_bmp_with_init_data(&bmp); | 
 | 419 |                     GrPixelConfig dstConfig = | 
 | 420 |                             SkImageInfo2GrPixelConfig(gReadPixelsConfigs[c].fColorType, | 
 | 421 |                                                       gReadPixelsConfigs[c].fAlphaType, | 
 | 422 |                                                       kLinear_SkColorProfileType); | 
 | 423 |                     uint32_t flags = 0; | 
 | 424 |                     if (gReadPixelsConfigs[c].fAlphaType == kUnpremul_SkAlphaType) { | 
 | 425 |                         flags = GrContext::kUnpremul_PixelOpsFlag; | 
| bsalomon@google.com | 67b915d | 2013-02-04 16:13:32 +0000 | [diff] [blame] | 426 |                     } | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 427 |                     bmp.lockPixels(); | 
 | 428 |                     bool success = texture->readPixels(srcRect.fLeft, srcRect.fTop, bmp.width(), | 
 | 429 |                                                        bmp.height(), dstConfig, bmp.getPixels(), | 
 | 430 |                                                        bmp.rowBytes(), flags); | 
 | 431 |                     bmp.unlockPixels(); | 
 | 432 |                     check_read(reporter, bmp, srcRect.fLeft, srcRect.fTop, | 
 | 433 |                                success, true); | 
| bsalomon@google.com | c698097 | 2011-11-02 19:57:21 +0000 | [diff] [blame] | 434 |                 } | 
 | 435 |             } | 
 | 436 |         } | 
 | 437 |     } | 
 | 438 | } | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 439 | DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadPixels_Texture, reporter, context) { | 
 | 440 |     // On the GPU we will also try reading back from a non-renderable texture. | 
 | 441 |     for (auto& origin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin}) { | 
 | 442 |         SkAutoTUnref<GrTexture> texture; | 
 | 443 |         GrSurfaceDesc desc; | 
 | 444 |         desc.fFlags = kRenderTarget_GrSurfaceFlag; | 
 | 445 |         desc.fWidth = DEV_W; | 
 | 446 |         desc.fHeight = DEV_H; | 
 | 447 |         desc.fConfig = kSkia8888_GrPixelConfig; | 
 | 448 |         desc.fOrigin = origin; | 
 | 449 |         desc.fFlags = kNone_GrSurfaceFlags; | 
 | 450 |         texture.reset(context->textureProvider()->createTexture(desc, false)); | 
 | 451 |         test_readpixels_texture(reporter, texture); | 
 | 452 |     } | 
 | 453 | } | 
 | 454 | #endif | 
| reed | 34482bb | 2015-09-16 12:50:27 -0700 | [diff] [blame] | 455 | ///////////////////// | 
 | 456 | #if SK_SUPPORT_GPU | 
 | 457 |  | 
 | 458 | // make_ringed_bitmap was lifted from gm/bleed.cpp, as that GM was what showed the following | 
 | 459 | // bug when a change was made to SkImage_Raster.cpp. It is possible that other test bitmaps | 
| halcanary | 6950de6 | 2015-11-07 05:29:00 -0800 | [diff] [blame] | 460 | // would also tickle https://bug.skia.org/4351 but this one is know to do it, so I've pasted the code | 
| reed | 34482bb | 2015-09-16 12:50:27 -0700 | [diff] [blame] | 461 | // here so we have a dependable repro case. | 
 | 462 |  | 
 | 463 | // Create a black&white checked texture with 2 1-pixel rings | 
 | 464 | // around the outside edge. The inner ring is red and the outer ring is blue. | 
 | 465 | static void make_ringed_bitmap(SkBitmap* result, int width, int height) { | 
 | 466 |     SkASSERT(0 == width % 2 && 0 == height % 2); | 
 | 467 |  | 
 | 468 |     static const SkPMColor kRed = SkPreMultiplyColor(SK_ColorRED); | 
 | 469 |     static const SkPMColor kBlue = SkPreMultiplyColor(SK_ColorBLUE); | 
 | 470 |     static const SkPMColor kBlack = SkPreMultiplyColor(SK_ColorBLACK); | 
 | 471 |     static const SkPMColor kWhite = SkPreMultiplyColor(SK_ColorWHITE); | 
 | 472 |  | 
 | 473 |     result->allocN32Pixels(width, height, true); | 
 | 474 |  | 
 | 475 |     SkPMColor* scanline = result->getAddr32(0, 0); | 
 | 476 |     for (int x = 0; x < width; ++x) { | 
 | 477 |         scanline[x] = kBlue; | 
 | 478 |     } | 
 | 479 |     scanline = result->getAddr32(0, 1); | 
 | 480 |     scanline[0] = kBlue; | 
 | 481 |     for (int x = 1; x < width - 1; ++x) { | 
 | 482 |         scanline[x] = kRed; | 
 | 483 |     } | 
 | 484 |     scanline[width-1] = kBlue; | 
 | 485 |  | 
 | 486 |     for (int y = 2; y < height/2; ++y) { | 
 | 487 |         scanline = result->getAddr32(0, y); | 
 | 488 |         scanline[0] = kBlue; | 
 | 489 |         scanline[1] = kRed; | 
 | 490 |         for (int x = 2; x < width/2; ++x) { | 
 | 491 |             scanline[x] = kBlack; | 
 | 492 |         } | 
 | 493 |         for (int x = width/2; x < width-2; ++x) { | 
 | 494 |             scanline[x] = kWhite; | 
 | 495 |         } | 
 | 496 |         scanline[width-2] = kRed; | 
 | 497 |         scanline[width-1] = kBlue; | 
 | 498 |     } | 
 | 499 |  | 
 | 500 |     for (int y = height/2; y < height-2; ++y) { | 
 | 501 |         scanline = result->getAddr32(0, y); | 
 | 502 |         scanline[0] = kBlue; | 
 | 503 |         scanline[1] = kRed; | 
 | 504 |         for (int x = 2; x < width/2; ++x) { | 
 | 505 |             scanline[x] = kWhite; | 
 | 506 |         } | 
 | 507 |         for (int x = width/2; x < width-2; ++x) { | 
 | 508 |             scanline[x] = kBlack; | 
 | 509 |         } | 
 | 510 |         scanline[width-2] = kRed; | 
 | 511 |         scanline[width-1] = kBlue; | 
 | 512 |     } | 
 | 513 |  | 
 | 514 |     scanline = result->getAddr32(0, height-2); | 
 | 515 |     scanline[0] = kBlue; | 
 | 516 |     for (int x = 1; x < width - 1; ++x) { | 
 | 517 |         scanline[x] = kRed; | 
 | 518 |     } | 
 | 519 |     scanline[width-1] = kBlue; | 
 | 520 |  | 
 | 521 |     scanline = result->getAddr32(0, height-1); | 
 | 522 |     for (int x = 0; x < width; ++x) { | 
 | 523 |         scanline[x] = kBlue; | 
 | 524 |     } | 
 | 525 |     result->setImmutable(); | 
 | 526 | } | 
 | 527 |  | 
 | 528 | static void compare_textures(skiatest::Reporter* reporter, GrTexture* txa, GrTexture* txb) { | 
 | 529 |     REPORTER_ASSERT(reporter, txa->width() == 2); | 
 | 530 |     REPORTER_ASSERT(reporter, txa->height() == 2); | 
 | 531 |     REPORTER_ASSERT(reporter, txb->width() == 2); | 
 | 532 |     REPORTER_ASSERT(reporter, txb->height() == 2); | 
 | 533 |     REPORTER_ASSERT(reporter, txa->config() == txb->config()); | 
 | 534 |  | 
 | 535 |     SkPMColor pixelsA[4], pixelsB[4]; | 
 | 536 |     REPORTER_ASSERT(reporter, txa->readPixels(0, 0, 2, 2, txa->config(), pixelsA)); | 
 | 537 |     REPORTER_ASSERT(reporter, txb->readPixels(0, 0, 2, 2, txa->config(), pixelsB)); | 
 | 538 |     REPORTER_ASSERT(reporter, 0 == memcmp(pixelsA, pixelsB, sizeof(pixelsA))); | 
 | 539 | } | 
 | 540 |  | 
 | 541 | static SkData* draw_into_surface(SkSurface* surf, const SkBitmap& bm, SkFilterQuality quality) { | 
 | 542 |     SkCanvas* canvas = surf->getCanvas(); | 
 | 543 |     canvas->clear(SK_ColorBLUE); | 
 | 544 |  | 
 | 545 |     SkPaint paint; | 
 | 546 |     paint.setFilterQuality(quality); | 
 | 547 |  | 
 | 548 |     canvas->translate(40, 100); | 
 | 549 |     canvas->rotate(30); | 
 | 550 |     canvas->scale(20, 30); | 
 | 551 |     canvas->translate(-SkScalarHalf(bm.width()), -SkScalarHalf(bm.height())); | 
 | 552 |     canvas->drawBitmap(bm, 0, 0, &paint); | 
 | 553 |  | 
 | 554 |     SkAutoTUnref<SkImage> image(surf->newImageSnapshot()); | 
 | 555 |     return image->encode(); | 
 | 556 | } | 
 | 557 |  | 
 | 558 | #include "SkStream.h" | 
 | 559 | static void dump_to_file(const char name[], SkData* data) { | 
 | 560 |     SkFILEWStream file(name); | 
 | 561 |     file.write(data->data(), data->size()); | 
 | 562 | } | 
 | 563 |  | 
 | 564 | /* | 
 | 565 |  *  Test two different ways to turn a subset of a bitmap into a texture | 
 | 566 |  *  - subset and then upload to a texture | 
 | 567 |  *  - upload to a texture and then subset | 
 | 568 |  * | 
 | 569 |  *  These two techniques result in the same pixels (ala readPixels) | 
 | 570 |  *  but when we draw them (rotated+scaled) we don't always get the same results. | 
 | 571 |  * | 
| halcanary | 6950de6 | 2015-11-07 05:29:00 -0800 | [diff] [blame] | 572 |  *  https://bug.skia.org/4351 | 
| reed | 34482bb | 2015-09-16 12:50:27 -0700 | [diff] [blame] | 573 |  */ | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 574 | DEF_GPUTEST_FOR_NATIVE_CONTEXT(ReadPixels_Subset_Gpu, reporter, context) { | 
| reed | 34482bb | 2015-09-16 12:50:27 -0700 | [diff] [blame] | 575 |     SkBitmap bitmap; | 
 | 576 |     make_ringed_bitmap(&bitmap, 6, 6); | 
 | 577 |     const SkIRect subset = SkIRect::MakeLTRB(2, 2, 4, 4); | 
 | 578 |  | 
 | 579 |     // make two textures... | 
 | 580 |     SkBitmap bm_subset, tx_subset; | 
 | 581 |  | 
 | 582 |     // ... one from a texture-subset | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 583 |     SkAutoTUnref<GrTexture> fullTx(GrRefCachedBitmapTexture(context, bitmap, | 
| bsalomon | afa95e2 | 2015-10-12 10:39:46 -0700 | [diff] [blame] | 584 |                                                             GrTextureParams::ClampNoFilter())); | 
| reed | 34482bb | 2015-09-16 12:50:27 -0700 | [diff] [blame] | 585 |     SkBitmap tx_full; | 
 | 586 |     GrWrapTextureInBitmap(fullTx, bitmap.width(), bitmap.height(), true, &tx_full); | 
 | 587 |     tx_full.extractSubset(&tx_subset, subset); | 
 | 588 |  | 
 | 589 |     // ... one from a bitmap-subset | 
 | 590 |     SkBitmap tmp_subset; | 
 | 591 |     bitmap.extractSubset(&tmp_subset, subset); | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 592 |     SkAutoTUnref<GrTexture> subsetTx(GrRefCachedBitmapTexture(context, tmp_subset, | 
| bsalomon | afa95e2 | 2015-10-12 10:39:46 -0700 | [diff] [blame] | 593 |                                                               GrTextureParams::ClampNoFilter())); | 
| reed | 34482bb | 2015-09-16 12:50:27 -0700 | [diff] [blame] | 594 |     GrWrapTextureInBitmap(subsetTx, tmp_subset.width(), tmp_subset.height(), true, &bm_subset); | 
 | 595 |  | 
 | 596 |     // did we get the same subset? | 
 | 597 |     compare_textures(reporter, bm_subset.getTexture(), tx_subset.getTexture()); | 
 | 598 |  | 
 | 599 |     // do they draw the same? | 
 | 600 |     const SkImageInfo info = SkImageInfo::MakeN32Premul(128, 128); | 
| kkinnunen | 1530283 | 2015-12-01 04:35:26 -0800 | [diff] [blame] | 601 |     SkAutoTUnref<SkSurface> surfA(SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0)); | 
 | 602 |     SkAutoTUnref<SkSurface> surfB(SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0)); | 
| reed | 34482bb | 2015-09-16 12:50:27 -0700 | [diff] [blame] | 603 |  | 
| reed | 34482bb | 2015-09-16 12:50:27 -0700 | [diff] [blame] | 604 |     if (false) { | 
| reed | 2fd18f2 | 2015-09-16 13:18:41 -0700 | [diff] [blame] | 605 |         // | 
 | 606 |         //  BUG: depending on the driver, if we calls this with various quality settings, it | 
 | 607 |         //       may fail. | 
 | 608 |         // | 
 | 609 |         SkFilterQuality quality = kLow_SkFilterQuality; | 
 | 610 |  | 
 | 611 |         SkAutoTUnref<SkData> dataA(draw_into_surface(surfA, bm_subset, quality)); | 
 | 612 |         SkAutoTUnref<SkData> dataB(draw_into_surface(surfB, tx_subset, quality)); | 
 | 613 |  | 
 | 614 |         REPORTER_ASSERT(reporter, dataA->equals(dataB)); | 
 | 615 |         if (false) { | 
 | 616 |             dump_to_file("test_image_A.png", dataA); | 
 | 617 |             dump_to_file("test_image_B.png", dataB); | 
 | 618 |         } | 
| reed | 34482bb | 2015-09-16 12:50:27 -0700 | [diff] [blame] | 619 |     } | 
 | 620 | } | 
 | 621 | #endif |