ReadPixelsTest.cpp revision d6176b0dcacb124539e0cfd051e6d93a9782f020
1c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 2c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com/* 3c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * Copyright 2011 Google Inc. 4c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * 5c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 6c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * found in the LICENSE file. 7c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com */ 8c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 9c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "Test.h" 10c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "SkCanvas.h" 11cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#include "SkColorPriv.h" 12cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#include "SkDevice.h" 134b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h" 14c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "SkRegion.h" 15cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU 16c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "SkGpuDevice.h" 17cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 18c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 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 25c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comnamespace { 26c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comSkPMColor getCanvasColor(int x, int y) { 27c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(x >= 0 && x < DEV_W); 28c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(y >= 0 && y < DEV_H); 296850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com 306850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com U8CPU r = x; 316850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com U8CPU g = y; 326850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com U8CPU b = 0xc; 336850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com 346850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com U8CPU a = 0xff; 35c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com switch ((x+y) % 5) { 366850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case 0: 376850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = 0xff; 386850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 396850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case 1: 406850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = 0x80; 416850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 426850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case 2: 436850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = 0xCC; 446850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 456850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case 4: 466850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = 0x01; 476850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 486850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case 3: 496850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = 0x00; 506850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 516850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 526850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com return SkPremultiplyARGBInline(a, r, g, b); 53c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 54d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 55c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comSkPMColor getBitmapColor(int x, int y, int w, int h) { 56c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int n = y * w + x; 576850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com 58c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com U8CPU b = n & 0xff; 59c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com U8CPU g = (n >> 8) & 0xff; 60c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com U8CPU r = (n >> 16) & 0xff; 61c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com return SkPackARGB32(0xff, r, g , b); 62c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 63c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 646850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.comSkPMColor convertConfig8888ToPMColor(SkCanvas::Config8888 config8888, 65c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com uint32_t color, 66c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com bool* premul) { 676850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com const uint8_t* c = reinterpret_cast<uint8_t*>(&color); 686850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com U8CPU a,r,g,b; 69c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com *premul = false; 706850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com switch (config8888) { 716850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case SkCanvas::kNative_Premul_Config8888: 726850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com return color; 736850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case SkCanvas::kNative_Unpremul_Config8888: 74c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com *premul = true; 756850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = SkGetPackedA32(color); 766850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com r = SkGetPackedR32(color); 776850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com g = SkGetPackedG32(color); 786850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com b = SkGetPackedB32(color); 796850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 806850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case SkCanvas::kBGRA_Unpremul_Config8888: 81c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com *premul = true; // fallthru 826850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case SkCanvas::kBGRA_Premul_Config8888: 836850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = static_cast<U8CPU>(c[3]); 846850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com r = static_cast<U8CPU>(c[2]); 856850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com g = static_cast<U8CPU>(c[1]); 866850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com b = static_cast<U8CPU>(c[0]); 876850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 886850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case SkCanvas::kRGBA_Unpremul_Config8888: 89c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com *premul = true; // fallthru 906850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com case SkCanvas::kRGBA_Premul_Config8888: 916850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com a = static_cast<U8CPU>(c[3]); 926850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com r = static_cast<U8CPU>(c[0]); 936850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com g = static_cast<U8CPU>(c[1]); 946850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com b = static_cast<U8CPU>(c[2]); 956850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com break; 966850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 97c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com if (*premul) { 986850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com r = SkMulDiv255Ceiling(r, a); 996850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com g = SkMulDiv255Ceiling(g, a); 1006850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com b = SkMulDiv255Ceiling(b, a); 1016850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 1026850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com return SkPackARGB32(a, r, g, b); 1036850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com} 1046850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com 105c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comvoid fillCanvas(SkCanvas* canvas) { 106c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com static SkBitmap bmp; 107c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (bmp.isNull()) { 108c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bmp.setConfig(SkBitmap::kARGB_8888_Config, DEV_W, DEV_H); 109c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bool alloc = bmp.allocPixels(); 110c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(alloc); 111c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkAutoLockPixels alp(bmp); 112c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels()); 113c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int y = 0; y < DEV_H; ++y) { 114c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int x = 0; x < DEV_W; ++x) { 115c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel()); 116c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com *pixel = getCanvasColor(x, y); 117c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 118c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 119c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 120c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com canvas->save(); 121c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com canvas->setMatrix(SkMatrix::I()); 122c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com canvas->clipRect(DEV_RECT_S, SkRegion::kReplace_Op); 123c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkPaint paint; 124c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com paint.setXfermodeMode(SkXfermode::kSrc_Mode); 125c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com canvas->drawBitmap(bmp, 0, 0, &paint); 126c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com canvas->restore(); 127c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 128d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 129c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comvoid fillBitmap(SkBitmap* bitmap) { 130c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(bitmap->lockPixelsAreWritable()); 131c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkAutoLockPixels alp(*bitmap); 132c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int w = bitmap->width(); 133c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int h = bitmap->height(); 134c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels()); 135c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int y = 0; y < h; ++y) { 136c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int x = 0; x < w; ++x) { 137c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel()); 138c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com *pixel = getBitmapColor(x, y, w, h); 139c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 140c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 141c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 142c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 143c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.combool checkPixel(SkPMColor a, SkPMColor b, bool didPremulConversion) { 144c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com if (!didPremulConversion) { 145c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com return a == b; 146c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com } 147c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t aA = static_cast<int32_t>(SkGetPackedA32(a)); 148c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t aR = static_cast<int32_t>(SkGetPackedR32(a)); 149c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t aG = static_cast<int32_t>(SkGetPackedG32(a)); 150c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t aB = SkGetPackedB32(a); 151c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com 152c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t bA = static_cast<int32_t>(SkGetPackedA32(b)); 153c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t bR = static_cast<int32_t>(SkGetPackedR32(b)); 154c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t bG = static_cast<int32_t>(SkGetPackedG32(b)); 155c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com int32_t bB = static_cast<int32_t>(SkGetPackedB32(b)); 156c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com 157c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com return aA == bA && 158c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com SkAbs32(aR - bR) <= 1 && 159c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com SkAbs32(aG - bG) <= 1 && 160c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com SkAbs32(aB - bB) <= 1; 161c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com} 162c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com 163c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// checks the bitmap contains correct pixels after the readPixels 164c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// if the bitmap was prefilled with pixels it checks that these weren't 165c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// overwritten in the area outside the readPixels. 166c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool checkRead(skiatest::Reporter* reporter, 167c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com const SkBitmap& bitmap, 168c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int x, int y, 1696850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com bool checkCanvasPixels, 1706850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com bool checkBitmapPixels, 1716850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkCanvas::Config8888 config8888) { 172c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config()); 173c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(!bitmap.isNull()); 1746850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkASSERT(checkCanvasPixels || checkBitmapPixels); 175d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 176c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int bw = bitmap.width(); 177c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int bh = bitmap.height(); 178c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 179c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh); 180c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect clippedSrcRect = DEV_RECT; 181c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (!clippedSrcRect.intersect(srcRect)) { 182c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com clippedSrcRect.setEmpty(); 183c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 184c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkAutoLockPixels alp(bitmap); 185c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com intptr_t pixels = reinterpret_cast<intptr_t>(bitmap.getPixels()); 186c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int by = 0; by < bh; ++by) { 187c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com for (int bx = 0; bx < bw; ++bx) { 188c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int devx = bx + srcRect.fLeft; 189c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int devy = by + srcRect.fTop; 190d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 191c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com uint32_t pixel = *reinterpret_cast<SkPMColor*>(pixels + by * bitmap.rowBytes() + bx * bitmap.bytesPerPixel()); 192c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 193c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (clippedSrcRect.contains(devx, devy)) { 1946850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com if (checkCanvasPixels) { 1956850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkPMColor canvasPixel = getCanvasColor(devx, devy); 196c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com bool didPremul; 197c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com SkPMColor pmPixel = convertConfig8888ToPMColor(config8888, pixel, &didPremul); 198c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com bool check; 199c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com REPORTER_ASSERT(reporter, check = checkPixel(pmPixel, canvasPixel, didPremul)); 200c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com if (!check) { 20172f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com return false; 2026850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 203c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 2046850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } else if (checkBitmapPixels) { 205c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com REPORTER_ASSERT(reporter, getBitmapColor(bx, by, bw, bh) == pixel); 206c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (getBitmapColor(bx, by, bw, bh) != pixel) { 20772f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com return false; 208c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 209c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 210c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 211c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 21272f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com return true; 213c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 214c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 215c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comenum BitmapInit { 216c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com kFirstBitmapInit = 0, 217d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 218c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com kNoPixels_BitmapInit = kFirstBitmapInit, 219c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com kTight_BitmapInit, 220c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com kRowBytes_BitmapInit, 221d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 222c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com kBitmapInitCnt 223c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}; 224c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 225c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comBitmapInit nextBMI(BitmapInit bmi) { 226c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int x = bmi; 227c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com return static_cast<BitmapInit>(++x); 228c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 229c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 230c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 231c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comvoid init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init) { 232c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int w = rect.width(); 233c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int h = rect.height(); 234c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com int rowBytes = 0; 235c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bool alloc = true; 236c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com switch (init) { 237c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com case kNoPixels_BitmapInit: 238c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com alloc = false; 239c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com case kTight_BitmapInit: 240c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com break; 241c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com case kRowBytes_BitmapInit: 242c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com rowBytes = w * sizeof(SkPMColor) + 16 * sizeof(SkPMColor); 243c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com break; 244c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com default: 245c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkASSERT(0); 246c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com break; 247c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 248c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bitmap->setConfig(SkBitmap::kARGB_8888_Config, w, h, rowBytes); 249c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (alloc) { 250c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bitmap->allocPixels(); 251c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 252c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 253c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 254c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comvoid ReadPixelsTest(skiatest::Reporter* reporter, GrContext* context) { 255c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkCanvas canvas; 256d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 257c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com const SkIRect testRects[] = { 258c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // entire thing 259c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com DEV_RECT, 260c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // larger on all sides 261c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10), 262c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // fully contained 263c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4), 264c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // outside top left 265c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, -1, -1), 266c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching top left corner 267c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, 0, 0), 268c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping top left corner 269c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H / 4), 270c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping top left and top right corners 271c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H / 4), 272c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching entire top edge 273c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, DEV_W + 10, 0), 274c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping top right corner 275c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H / 4), 276c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // contained in x, overlapping top edge 277c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(DEV_W / 4, -10, 3 * DEV_W / 4, DEV_H / 4), 278c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // outside top right corner 279c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(DEV_W + 1, -10, DEV_W + 10, -1), 280c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching top right corner 281c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(DEV_W, -10, DEV_W + 10, 0), 282c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping top left and bottom left corners 283c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H + 10), 284c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching entire left edge 285c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, -10, 0, DEV_H + 10), 286c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping bottom left corner 287c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W / 4, DEV_H + 10), 288c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // contained in y, overlapping left edge 289c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, DEV_H / 4, DEV_W / 4, 3 * DEV_H / 4), 290c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // outside bottom left corner 291c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, DEV_H + 1, -1, DEV_H + 10), 292c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching bottom left corner 293c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, DEV_H, 0, DEV_H + 10), 294c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping bottom left and bottom right corners 295c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10), 296c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // touching entire left edge 297c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(0, DEV_H, DEV_W, DEV_H + 10), 298c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping bottom right corner 299c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(3 * DEV_W / 4, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10), 300c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com // overlapping top right and bottom right corners 301c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H + 10), 302c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com }; 303c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 304b9f026fb219091716debcd57cb13b593faa97ee5bsalomon@google.com for (int dtype = 0; dtype < 2; ++dtype) { 305c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 306c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (0 == dtype) { 3076850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com canvas.setDevice(new SkDevice(SkBitmap::kARGB_8888_Config, 3086850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com DEV_W, 3096850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com DEV_H, 3106850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com false))->unref(); 311c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } else { 312cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com// GPU device known not to work in the fixed pt build. 313cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if defined(SK_SCALAR_IS_FIXED) || !SK_SUPPORT_GPU 314c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com continue; 315cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else 3166850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com canvas.setDevice(new SkGpuDevice(context, 3176850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkBitmap::kARGB_8888_Config, 3186850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com DEV_W, 3196850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com DEV_H))->unref(); 320cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 321c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 322c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com fillCanvas(&canvas); 323c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 3246850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com static const SkCanvas::Config8888 gReadConfigs[] = { 3256850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkCanvas::kNative_Premul_Config8888, 3266850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkCanvas::kNative_Unpremul_Config8888, 3278688e5b7d164a219795944c76e47691aab85c397djsollen@google.com/** 3288688e5b7d164a219795944c76e47691aab85c397djsollen@google.com * There is a bug in Ganesh (http://code.google.com/p/skia/issues/detail?id=438) 3298688e5b7d164a219795944c76e47691aab85c397djsollen@google.com * that causes the readback of pixels from BGRA canvas to an RGBA bitmap to 3308688e5b7d164a219795944c76e47691aab85c397djsollen@google.com * fail. This should be removed as soon as the issue above is resolved. 3318688e5b7d164a219795944c76e47691aab85c397djsollen@google.com */ 3328688e5b7d164a219795944c76e47691aab85c397djsollen@google.com#if !defined(SK_BUILD_FOR_ANDROID) 3336850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkCanvas::kBGRA_Premul_Config8888, 3346850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkCanvas::kBGRA_Unpremul_Config8888, 3358688e5b7d164a219795944c76e47691aab85c397djsollen@google.com#endif 3366850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkCanvas::kRGBA_Premul_Config8888, 3376850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkCanvas::kRGBA_Unpremul_Config8888, 3386850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com }; 339f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com for (size_t rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) { 3406850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com const SkIRect& srcRect = testRects[rect]; 3416850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com for (BitmapInit bmi = kFirstBitmapInit; 3426850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com bmi < kBitmapInitCnt; 3436850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com bmi = nextBMI(bmi)) { 344f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com for (size_t c = 0; c < SK_ARRAY_COUNT(gReadConfigs); ++c) { 3456850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkCanvas::Config8888 config8888 = gReadConfigs[c]; 3466850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkBitmap bmp; 3476850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com init_bitmap(&bmp, srcRect, bmi); 348c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 3496850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com // if the bitmap has pixels allocated before the readPixels, 3506850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com // note that and fill them with pattern 3516850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com bool startsWithPixels = !bmp.isNull(); 3526850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com if (startsWithPixels) { 3536850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com fillBitmap(&bmp); 3546850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 355c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 3566850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com bool success = 3576850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com canvas.readPixels(&bmp, srcRect.fLeft, 3586850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com srcRect.fTop, config8888); 359c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 360c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com // we expect to succeed when the read isn't fully clipped 361c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com // out. 362c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RECT); 3636850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com // determine whether we expected the read to succeed. 3646850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com REPORTER_ASSERT(reporter, success == expectSuccess); 365c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 3666850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com if (success || startsWithPixels) { 3676850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop, 3686850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com success, startsWithPixels, config8888); 3696850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } else { 3706850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com // if we had no pixels beforehand and the readPixels 3716850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com // failed then our bitmap should still not have pixels 3726850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com REPORTER_ASSERT(reporter, bmp.isNull()); 3736850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 3746850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com } 3756850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com // check the old webkit version of readPixels that clips the 3766850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com // bitmap size 377c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkBitmap wkbmp; 3786850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com bool success = canvas.readPixels(srcRect, &wkbmp); 379c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkIRect clippedRect = DEV_RECT; 380c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (clippedRect.intersect(srcRect)) { 381c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com REPORTER_ASSERT(reporter, success); 3826850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com checkRead(reporter, wkbmp, clippedRect.fLeft, 3836850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com clippedRect.fTop, true, false, 3846850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com SkCanvas::kNative_Premul_Config8888); 385c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } else { 386c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com REPORTER_ASSERT(reporter, !success); 387c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 388c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 389c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 390c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 391c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 392c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com} 393c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 394c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "TestClassDef.h" 395c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comDEFINE_GPUTESTCLASS("ReadPixels", ReadPixelsTestClass, ReadPixelsTest) 396c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 397