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