1c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com/* 2c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * Copyright 2011 Google Inc. 3c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * 4c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 5c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * found in the LICENSE file. 6c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com */ 7c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 873672254a3e498081967d00d27b17ada443e2ab2robertphillips@google.com#include "SkBitmapDevice.h" 9c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "SkCanvas.h" 10cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#include "SkColorPriv.h" 114b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h" 12c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "SkRegion.h" 134ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "Test.h" 144ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org 15cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU 1667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#include "GrContextFactory.h" 178f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkGpuDevice.h" 18cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 19c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 20c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comstatic const int DEV_W = 100, DEV_H = 100; 21c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comstatic const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H); 22d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comstatic const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1, 23c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com DEV_H * SK_Scalar1); 24c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 25ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic SkPMColor getCanvasColor(int x, int y) { 26c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(x >= 0 && x < DEV_W); 27c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(y >= 0 && y < DEV_H); 286850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com 296850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com U8CPU r = x; 306850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com U8CPU g = y; 316850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com U8CPU b = 0xc; 326850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com 336850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com U8CPU a = 0xff; 34c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com switch ((x+y) % 5) { 356850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case 0: 366850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = 0xff; 376850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 386850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case 1: 396850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = 0x80; 406850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 416850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case 2: 426850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = 0xCC; 436850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 446850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case 4: 456850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = 0x01; 466850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 476850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case 3: 486850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = 0x00; 496850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 506850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 516850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com return SkPremultiplyARGBInline(a, r, g, b); 52c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 53d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 54ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic SkPMColor getBitmapColor(int x, int y, int w) { 55c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int n = y * w + x; 566850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com 57c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com U8CPU b = n & 0xff; 58c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com U8CPU g = (n >> 8) & 0xff; 59c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com U8CPU r = (n >> 16) & 0xff; 60c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com return SkPackARGB32(0xff, r, g , b); 61c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 62c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 63a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgstatic SkPMColor convertToPMColor(SkColorType ct, SkAlphaType at, const uint32_t* addr, 64a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org bool* doUnpremul) { 65a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org *doUnpremul = (kUnpremul_SkAlphaType == at); 66a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org 67a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org const uint8_t* c = reinterpret_cast<const uint8_t*>(addr); 686850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com U8CPU a,r,g,b; 69a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org switch (ct) { 70a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org case kBGRA_8888_SkColorType: 716850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com b = static_cast<U8CPU>(c[0]); 72a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org g = static_cast<U8CPU>(c[1]); 73a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org r = static_cast<U8CPU>(c[2]); 746850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = static_cast<U8CPU>(c[3]); 75a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org break; 76a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org case kRGBA_8888_SkColorType: 776850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com r = static_cast<U8CPU>(c[0]); 786850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com g = static_cast<U8CPU>(c[1]); 796850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com b = static_cast<U8CPU>(c[2]); 80a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org a = static_cast<U8CPU>(c[3]); 816850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 82ccaa002dd81a6a8bd5acb7a2fa69a2437873c1fdbsalomon@google.com default: 83a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org SkDEBUGFAIL("Unexpected colortype"); 84ccaa002dd81a6a8bd5acb7a2fa69a2437873c1fdbsalomon@google.com return 0; 856850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 86a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org 87a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org if (*doUnpremul) { 886850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com r = SkMulDiv255Ceiling(r, a); 896850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com g = SkMulDiv255Ceiling(g, a); 906850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com b = SkMulDiv255Ceiling(b, a); 916850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 926850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com return SkPackARGB32(a, r, g, b); 936850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com} 946850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com 95ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic void fillCanvas(SkCanvas* canvas) { 96c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com static SkBitmap bmp; 97c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (bmp.isNull()) { 98fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org SkDEBUGCODE(bool alloc =) bmp.allocN32Pixels(DEV_W, DEV_H); 99c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(alloc); 100c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkAutoLockPixels alp(bmp); 101c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels()); 102c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int y = 0; y < DEV_H; ++y) { 103c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int x = 0; x < DEV_W; ++x) { 104c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel()); 105c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com *pixel = getCanvasColor(x, y); 106c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 107c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 108c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 109c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com canvas->save(); 110c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com canvas->setMatrix(SkMatrix::I()); 111c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com canvas->clipRect(DEV_RECT_S, SkRegion::kReplace_Op); 112c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkPaint paint; 113c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com paint.setXfermodeMode(SkXfermode::kSrc_Mode); 114c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com canvas->drawBitmap(bmp, 0, 0, &paint); 115c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com canvas->restore(); 116c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 117d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 118ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic void fillBitmap(SkBitmap* bitmap) { 119c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(bitmap->lockPixelsAreWritable()); 120c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkAutoLockPixels alp(*bitmap); 121c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int w = bitmap->width(); 122c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int h = bitmap->height(); 123c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels()); 124c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int y = 0; y < h; ++y) { 125c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int x = 0; x < w; ++x) { 126c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel()); 12754f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.com *pixel = getBitmapColor(x, y, w); 128c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 129c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 130c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 131c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 132ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic bool checkPixel(SkPMColor a, SkPMColor b, bool didPremulConversion) { 133c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com if (!didPremulConversion) { 134c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com return a == b; 135c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com } 136c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t aA = static_cast<int32_t>(SkGetPackedA32(a)); 137c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t aR = static_cast<int32_t>(SkGetPackedR32(a)); 138c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t aG = static_cast<int32_t>(SkGetPackedG32(a)); 139c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t aB = SkGetPackedB32(a); 140c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com 141c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t bA = static_cast<int32_t>(SkGetPackedA32(b)); 142c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t bR = static_cast<int32_t>(SkGetPackedR32(b)); 143c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t bG = static_cast<int32_t>(SkGetPackedG32(b)); 144c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t bB = static_cast<int32_t>(SkGetPackedB32(b)); 145c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com 146c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com return aA == bA && 147c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com SkAbs32(aR - bR) <= 1 && 148c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com SkAbs32(aG - bG) <= 1 && 149c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com SkAbs32(aB - bB) <= 1; 150c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com} 151c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com 152c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// checks the bitmap contains correct pixels after the readPixels 153c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// if the bitmap was prefilled with pixels it checks that these weren't 154c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// overwritten in the area outside the readPixels. 155ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic bool checkRead(skiatest::Reporter* reporter, 156ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.org const SkBitmap& bitmap, 157ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.org int x, int y, 158ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.org bool checkCanvasPixels, 159a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org bool checkBitmapPixels) { 160a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org SkASSERT(4 == bitmap.bytesPerPixel()); 161c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(!bitmap.isNull()); 1626850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkASSERT(checkCanvasPixels || checkBitmapPixels); 163d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 164a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org const SkColorType ct = bitmap.colorType(); 165a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org const SkAlphaType at = bitmap.alphaType(); 166a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org 167c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int bw = bitmap.width(); 168c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int bh = bitmap.height(); 169c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 170c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh); 171c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect clippedSrcRect = DEV_RECT; 172c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (!clippedSrcRect.intersect(srcRect)) { 173c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com clippedSrcRect.setEmpty(); 174c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 175c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkAutoLockPixels alp(bitmap); 176c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int by = 0; by < bh; ++by) { 177c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int bx = 0; bx < bw; ++bx) { 178c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int devx = bx + srcRect.fLeft; 179c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int devy = by + srcRect.fTop; 180d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 181a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org const uint32_t* pixel = bitmap.getAddr32(bx, by); 182c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 183c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (clippedSrcRect.contains(devx, devy)) { 1846850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com if (checkCanvasPixels) { 1856850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkPMColor canvasPixel = getCanvasColor(devx, devy); 186c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com bool didPremul; 187a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org SkPMColor pmPixel = convertToPMColor(ct, at, pixel, &didPremul); 188c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com bool check; 189c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com REPORTER_ASSERT(reporter, check = checkPixel(pmPixel, canvasPixel, didPremul)); 190c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com if (!check) { 19172f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com return false; 1926850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 193c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 1946850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } else if (checkBitmapPixels) { 195a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org REPORTER_ASSERT(reporter, getBitmapColor(bx, by, bw) == *pixel); 196a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org if (getBitmapColor(bx, by, bw) != *pixel) { 19772f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com return false; 198c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 199c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 200c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 201c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 20272f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com return true; 203c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 204c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 205c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comenum BitmapInit { 206c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com kFirstBitmapInit = 0, 207d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 208c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com kNoPixels_BitmapInit = kFirstBitmapInit, 209c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com kTight_BitmapInit, 210c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com kRowBytes_BitmapInit, 211d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 212c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com kBitmapInitCnt 213c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}; 214c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 215ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic BitmapInit nextBMI(BitmapInit bmi) { 216c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int x = bmi; 217c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com return static_cast<BitmapInit>(++x); 218c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 219c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 220a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgstatic void init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init, SkColorType ct, 221a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org SkAlphaType at) { 222a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), ct, at); 223fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org size_t rowBytes = 0; 224c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bool alloc = true; 225c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com switch (init) { 226c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com case kNoPixels_BitmapInit: 227c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com alloc = false; 228c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com case kTight_BitmapInit: 229c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com break; 230c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com case kRowBytes_BitmapInit: 231fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org rowBytes = (info.width() + 16) * sizeof(SkPMColor); 232c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com break; 233c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com default: 234c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(0); 235c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com break; 236c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 23702d6f546161e2c98d69066373cec3f54f3c46252skia.committer@gmail.com 238c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (alloc) { 239fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org bitmap->allocPixels(info); 240fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org } else { 241a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org bitmap->setInfo(info, rowBytes); 242c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 243c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 244c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 2454ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.orgDEF_GPUTEST(ReadPixels, reporter, factory) { 246c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com const SkIRect testRects[] = { 247c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // entire thing 248c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com DEV_RECT, 249c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // larger on all sides 250c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10), 251c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // fully contained 252c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4), 253c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // outside top left 254c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, -1, -1), 255c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching top left corner 256c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, 0, 0), 257c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping top left corner 258c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H / 4), 259c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping top left and top right corners 260c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H / 4), 261c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching entire top edge 262c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, DEV_W + 10, 0), 263c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping top right corner 264c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H / 4), 265c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // contained in x, overlapping top edge 266c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(DEV_W / 4, -10, 3 * DEV_W / 4, DEV_H / 4), 267c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // outside top right corner 268c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(DEV_W + 1, -10, DEV_W + 10, -1), 269c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching top right corner 270c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(DEV_W, -10, DEV_W + 10, 0), 271c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping top left and bottom left corners 272c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H + 10), 273c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching entire left edge 274c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, 0, DEV_H + 10), 275c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping bottom left corner 276c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W / 4, DEV_H + 10), 277c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // contained in y, overlapping left edge 278c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, DEV_H / 4, DEV_W / 4, 3 * DEV_H / 4), 279c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // outside bottom left corner 280c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, DEV_H + 1, -1, DEV_H + 10), 281c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching bottom left corner 282c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, DEV_H, 0, DEV_H + 10), 283c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping bottom left and bottom right corners 284c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10), 285c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching entire left edge 286c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(0, DEV_H, DEV_W, DEV_H + 10), 287c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping bottom right corner 288c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(3 * DEV_W / 4, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10), 289c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping top right and bottom right corners 290c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H + 10), 291c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com }; 292c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 2933cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org for (int dtype = 0; dtype < 3; ++dtype) { 29467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com int glCtxTypeCnt = 1; 29567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#if SK_SUPPORT_GPU 29667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com if (0 != dtype) { 29767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt; 29867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com } 29967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#endif 30067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) { 3011f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkAutoTUnref<SkBaseDevice> device; 30267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com if (0 == dtype) { 30315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkImageInfo info = SkImageInfo::MakeN32Premul(DEV_W, DEV_H); 30415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org device.reset(SkBitmapDevice::Create(info)); 30567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com } else { 30667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#if SK_SUPPORT_GPU 30767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com GrContextFactory::GLContextType type = 30867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com static_cast<GrContextFactory::GLContextType>(glCtxType); 30967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com if (!GrContextFactory::IsRenderingGLContext(type)) { 31067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com continue; 31167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com } 31267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com GrContext* context = factory->get(type); 31367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com if (NULL == context) { 31467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com continue; 31567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com } 3163cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org GrTextureDesc desc; 3173cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 3183cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org desc.fWidth = DEV_W; 3193cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org desc.fHeight = DEV_H; 320fec0bc3fc13481f5bcb341ab2d2d695911f39bd4bsalomon@google.com desc.fConfig = kSkia8888_GrPixelConfig; 3213cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org desc.fOrigin = 1 == dtype ? kBottomLeft_GrSurfaceOrigin 3223cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org : kTopLeft_GrSurfaceOrigin; 3233cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org GrAutoScratchTexture ast(context, desc, GrContext::kExact_ScratchTexMatch); 3243cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org SkAutoTUnref<GrTexture> tex(ast.detach()); 3253cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org device.reset(new SkGpuDevice(context, tex)); 326cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else 32767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com continue; 328cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 32967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com } 33067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com SkCanvas canvas(device); 33167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com fillCanvas(&canvas); 332c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 333a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org static const struct { 334a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org SkColorType fColorType; 335a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org SkAlphaType fAlphaType; 336a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org } gReadConfigs[] = { 337a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org { kRGBA_8888_SkColorType, kPremul_SkAlphaType }, 338a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType }, 339a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org { kBGRA_8888_SkColorType, kPremul_SkAlphaType }, 340a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType }, 34167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com }; 34267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com for (size_t rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) { 34367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com const SkIRect& srcRect = testRects[rect]; 344a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org for (BitmapInit bmi = kFirstBitmapInit; bmi < kBitmapInitCnt; bmi = nextBMI(bmi)) { 34567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com for (size_t c = 0; c < SK_ARRAY_COUNT(gReadConfigs); ++c) { 34667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com SkBitmap bmp; 347a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org init_bitmap(&bmp, srcRect, bmi, 348a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org gReadConfigs[c].fColorType, gReadConfigs[c].fAlphaType); 34967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com 35067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com // if the bitmap has pixels allocated before the readPixels, 35167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com // note that and fill them with pattern 35267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com bool startsWithPixels = !bmp.isNull(); 35367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com if (startsWithPixels) { 35467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com fillBitmap(&bmp); 35567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com } 35667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com uint32_t idBefore = canvas.getDevice()->accessBitmap(false).getGenerationID(); 357a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org bool success = canvas.readPixels(&bmp, srcRect.fLeft, srcRect.fTop); 35867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com uint32_t idAfter = canvas.getDevice()->accessBitmap(false).getGenerationID(); 35967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com 36067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com // we expect to succeed when the read isn't fully clipped 36167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com // out. 36267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RECT); 36367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com // determine whether we expected the read to succeed. 36467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com REPORTER_ASSERT(reporter, success == expectSuccess); 36567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com // read pixels should never change the gen id 36667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com REPORTER_ASSERT(reporter, idBefore == idAfter); 36767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com 36867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com if (success || startsWithPixels) { 36967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop, 370a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org success, startsWithPixels); 37167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com } else { 37267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com // if we had no pixels beforehand and the readPixels 37367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com // failed then our bitmap should still not have pixels 37467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com REPORTER_ASSERT(reporter, bmp.isNull()); 37567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com } 3766850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 37767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com // check the old webkit version of readPixels that clips the 37867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com // bitmap size 37967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com SkBitmap wkbmp; 38067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com bool success = canvas.readPixels(srcRect, &wkbmp); 38167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com SkIRect clippedRect = DEV_RECT; 38267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com if (clippedRect.intersect(srcRect)) { 38367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com REPORTER_ASSERT(reporter, success); 38428fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org REPORTER_ASSERT(reporter, kN32_SkColorType == wkbmp.colorType()); 385a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org REPORTER_ASSERT(reporter, kPremul_SkAlphaType == wkbmp.alphaType()); 38667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com checkRead(reporter, wkbmp, clippedRect.fLeft, 387a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org clippedRect.fTop, true, false); 3886850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } else { 38967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com REPORTER_ASSERT(reporter, !success); 3906850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 3916850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 392c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 393c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 394c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 395c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 396