ReadPixelsTest.cpp revision 6850eab42ba4c2a7033a99824b02a2846ce0ef2a
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"
11c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "SkRegion.h"
12c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "SkGpuDevice.h"
13c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
14c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
15c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comstatic const int DEV_W = 100, DEV_H = 100;
16c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comstatic const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);
17c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comstatic const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1,
18c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                                                DEV_H * SK_Scalar1);
19c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
20c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comnamespace {
21c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comSkPMColor getCanvasColor(int x, int y) {
22c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkASSERT(x >= 0 && x < DEV_W);
23c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkASSERT(y >= 0 && y < DEV_H);
246850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com
256850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    U8CPU r = x;
266850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    U8CPU g = y;
276850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    U8CPU b = 0xc;
286850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com
296850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    U8CPU a = 0xff;
306850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    switch (x % 5) {
316850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case 0:
326850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            a = 0xff;
336850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            break;
346850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case 1:
356850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            a = 0x80;
366850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            break;
376850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case 2:
386850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            a = 0xCC;
396850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            break;
406850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case 4:
416850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            a = 0x01;
426850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            break;
436850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case 3:
446850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            a = 0x00;
456850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            break;
466850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    }
476850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    return SkPremultiplyARGBInline(a, r, g, b);
48c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
49c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
50c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comSkPMColor getBitmapColor(int x, int y, int w, int h) {
51c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int n = y * w + x;
526850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com
53c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    U8CPU b = n & 0xff;
54c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    U8CPU g = (n >> 8) & 0xff;
55c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    U8CPU r = (n >> 16) & 0xff;
56c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    return SkPackARGB32(0xff, r, g , b);
57c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
58c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
596850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.comSkPMColor convertConfig8888ToPMColor(SkCanvas::Config8888 config8888,
606850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                                     uint32_t color) {
616850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    const uint8_t* c = reinterpret_cast<uint8_t*>(&color);
626850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    U8CPU a,r,g,b;
636850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    bool mul = false;
646850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    switch (config8888) {
656850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case SkCanvas::kNative_Premul_Config8888:
666850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            return color;
676850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case SkCanvas::kNative_Unpremul_Config8888:
686850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            mul = true;
696850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            a = SkGetPackedA32(color);
706850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            r = SkGetPackedR32(color);
716850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            g = SkGetPackedG32(color);
726850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            b = SkGetPackedB32(color);
736850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            break;
746850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case SkCanvas::kBGRA_Unpremul_Config8888:
756850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            mul = true; // fallthru
766850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case SkCanvas::kBGRA_Premul_Config8888:
776850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            a = static_cast<U8CPU>(c[3]);
786850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            r = static_cast<U8CPU>(c[2]);
796850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            g = static_cast<U8CPU>(c[1]);
806850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            b = static_cast<U8CPU>(c[0]);
816850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            break;
826850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case SkCanvas::kRGBA_Unpremul_Config8888:
836850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            mul = true; // fallthru
846850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        case SkCanvas::kRGBA_Premul_Config8888:
856850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            a = static_cast<U8CPU>(c[3]);
866850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            r = static_cast<U8CPU>(c[0]);
876850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            g = static_cast<U8CPU>(c[1]);
886850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            b = static_cast<U8CPU>(c[2]);
896850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            break;
906850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    }
916850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    if (mul) {
926850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        r = SkMulDiv255Ceiling(r, a);
936850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        g = SkMulDiv255Ceiling(g, a);
946850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        b = SkMulDiv255Ceiling(b, a);
956850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    }
966850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    return SkPackARGB32(a, r, g, b);
976850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com}
986850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com
99c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comvoid fillCanvas(SkCanvas* canvas) {
100c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    static SkBitmap bmp;
101c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    if (bmp.isNull()) {
102c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        bmp.setConfig(SkBitmap::kARGB_8888_Config, DEV_W, DEV_H);
103c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        bool alloc = bmp.allocPixels();
104c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkASSERT(alloc);
105c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkAutoLockPixels alp(bmp);
106c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels());
107c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        for (int y = 0; y < DEV_H; ++y) {
108c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            for (int x = 0; x < DEV_W; ++x) {
109c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel());
110c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                *pixel = getCanvasColor(x, y);
111c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            }
112c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        }
113c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
114c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    canvas->save();
115c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    canvas->setMatrix(SkMatrix::I());
116c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    canvas->clipRect(DEV_RECT_S, SkRegion::kReplace_Op);
117c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkPaint paint;
118c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
119c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    canvas->drawBitmap(bmp, 0, 0, &paint);
120c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    canvas->restore();
121c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
122c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
123c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comvoid fillBitmap(SkBitmap* bitmap) {
124c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkASSERT(bitmap->lockPixelsAreWritable());
125c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkAutoLockPixels alp(*bitmap);
126c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int w = bitmap->width();
127c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int h = bitmap->height();
128c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels());
129c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    for (int y = 0; y < h; ++y) {
130c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        for (int x = 0; x < w; ++x) {
131c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel());
132c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            *pixel = getBitmapColor(x, y, w, h);
133c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        }
134c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
135c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
136c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
137c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// checks the bitmap contains correct pixels after the readPixels
138c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// if the bitmap was prefilled with pixels it checks that these weren't
139c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// overwritten in the area outside the readPixels.
140c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool checkRead(skiatest::Reporter* reporter,
141c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com               const SkBitmap& bitmap,
142c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com               int x, int y,
1436850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com               bool checkCanvasPixels,
1446850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com               bool checkBitmapPixels,
1456850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com               SkCanvas::Config8888 config8888) {
146c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
147c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkASSERT(!bitmap.isNull());
1486850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    SkASSERT(checkCanvasPixels || checkBitmapPixels);
149c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
150c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int bw = bitmap.width();
151c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int bh = bitmap.height();
152c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
153c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh);
154c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkIRect clippedSrcRect = DEV_RECT;
155c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    if (!clippedSrcRect.intersect(srcRect)) {
156c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        clippedSrcRect.setEmpty();
157c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
158c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
159c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkAutoLockPixels alp(bitmap);
160c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    intptr_t pixels = reinterpret_cast<intptr_t>(bitmap.getPixels());
161c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    for (int by = 0; by < bh; ++by) {
162c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        for (int bx = 0; bx < bw; ++bx) {
163c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            int devx = bx + srcRect.fLeft;
164c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            int devy = by + srcRect.fTop;
165c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
166c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            SkPMColor pixel = *reinterpret_cast<SkPMColor*>(pixels + by * bitmap.rowBytes() + bx * bitmap.bytesPerPixel());
167c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
168c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            if (clippedSrcRect.contains(devx, devy)) {
1696850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                if (checkCanvasPixels) {
1706850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    SkPMColor canvasPixel = getCanvasColor(devx, devy);
1716850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    pixel = convertConfig8888ToPMColor(config8888, pixel);
1726850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    REPORTER_ASSERT(reporter, canvasPixel == pixel);
1736850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    if (getCanvasColor(devx, devy) != pixel) {
1746850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                        return false;
1756850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    }
176c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                }
1776850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            } else if (checkBitmapPixels) {
178c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                REPORTER_ASSERT(reporter, getBitmapColor(bx, by, bw, bh) == pixel);
179c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                if (getBitmapColor(bx, by, bw, bh) != pixel) {
180c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                    return false;
181c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                }
182c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            }
183c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        }
184c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
185c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    return true;
186c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
187c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
188c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comenum BitmapInit {
189c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    kFirstBitmapInit = 0,
190c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
191c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    kNoPixels_BitmapInit = kFirstBitmapInit,
192c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    kTight_BitmapInit,
193c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    kRowBytes_BitmapInit,
194c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
195c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    kBitmapInitCnt
196c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com};
197c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
198c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comBitmapInit nextBMI(BitmapInit bmi) {
199c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int x = bmi;
200c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    return static_cast<BitmapInit>(++x);
201c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
202c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
203c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
204c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comvoid init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init) {
205c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int w = rect.width();
206c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int h = rect.height();
207c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int rowBytes = 0;
208c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    bool alloc = true;
209c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    switch (init) {
210c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        case kNoPixels_BitmapInit:
211c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            alloc = false;
212c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        case kTight_BitmapInit:
213c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            break;
214c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        case kRowBytes_BitmapInit:
215c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            rowBytes = w * sizeof(SkPMColor) + 16 * sizeof(SkPMColor);
216c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            break;
217c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        default:
218c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            SkASSERT(0);
219c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            break;
220c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
221c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    bitmap->setConfig(SkBitmap::kARGB_8888_Config, w, h, rowBytes);
222c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    if (alloc) {
223c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        bitmap->allocPixels();
224c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
225c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
226c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
227c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comvoid ReadPixelsTest(skiatest::Reporter* reporter, GrContext* context) {
228c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkCanvas canvas;
229c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
230c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    const SkIRect testRects[] = {
231c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // entire thing
232c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        DEV_RECT,
233c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // larger on all sides
234c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10),
235c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // fully contained
236c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4),
237c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // outside top left
238c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, -1, -1),
239c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching top left corner
240c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, 0, 0),
241c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping top left corner
242c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H / 4),
243c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping top left and top right corners
244c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, DEV_H / 4),
245c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching entire top edge
246c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, 0),
247c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping top right corner
248c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W  + 10, DEV_H / 4),
249c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // contained in x, overlapping top edge
250c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(DEV_W / 4, -10, 3 * DEV_W  / 4, DEV_H / 4),
251c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // outside top right corner
252c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(DEV_W + 1, -10, DEV_W + 10, -1),
253c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching top right corner
254c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(DEV_W, -10, DEV_W + 10, 0),
255c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping top left and bottom left corners
256c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H + 10),
257c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching entire left edge
258c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, 0, DEV_H + 10),
259c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping bottom left corner
260c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W / 4, DEV_H + 10),
261c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // contained in y, overlapping left edge
262c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H / 4, DEV_W / 4, 3 * DEV_H / 4),
263c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // outside bottom left corner
264c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H + 1, -1, DEV_H + 10),
265c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching bottom left corner
266c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H, 0, DEV_H + 10),
267c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping bottom left and bottom right corners
268c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
269c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching entire left edge
270c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(0, DEV_H, DEV_W, DEV_H + 10),
271c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping bottom right corner
272c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
273c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping top right and bottom right corners
274c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H + 10),
275c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    };
276c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
277c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    for (int dtype = 0; dtype < 2; ++dtype) {
278c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
279c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        if (0 == dtype) {
2806850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            canvas.setDevice(new SkDevice(SkBitmap::kARGB_8888_Config,
2816850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                                          DEV_W,
2826850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                                          DEV_H,
2836850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                                          false))->unref();
284c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        } else {
285c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#if SK_SCALAR_IS_FIXED
286c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            // GPU device known not to work in the fixed pt build.
287c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            continue;
288c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#endif
2896850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            canvas.setDevice(new SkGpuDevice(context,
2906850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                                             SkBitmap::kARGB_8888_Config,
2916850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                                             DEV_W,
2926850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                                             DEV_H))->unref();
293c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        }
294c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        fillCanvas(&canvas);
295c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
2966850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        static const SkCanvas::Config8888 gReadConfigs[] = {
2976850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            SkCanvas::kNative_Premul_Config8888,
2986850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            SkCanvas::kNative_Unpremul_Config8888,
2996850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            SkCanvas::kBGRA_Premul_Config8888,
3006850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            SkCanvas::kBGRA_Unpremul_Config8888,
3016850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            SkCanvas::kRGBA_Premul_Config8888,
3026850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            SkCanvas::kRGBA_Unpremul_Config8888,
3036850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        };
304c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        for (int rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) {
3056850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            const SkIRect& srcRect = testRects[rect];
3066850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            for (BitmapInit bmi = kFirstBitmapInit;
3076850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                 bmi < kBitmapInitCnt;
3086850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                 bmi = nextBMI(bmi)) {
3096850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                for (int c = 0; c < SK_ARRAY_COUNT(gReadConfigs); ++c) {
3106850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    SkCanvas::Config8888 config8888 = gReadConfigs[c];
3116850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    SkBitmap bmp;
3126850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    init_bitmap(&bmp, srcRect, bmi);
313c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
3146850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    // if the bitmap has pixels allocated before the readPixels,
3156850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    // note that and fill them with pattern
3166850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    bool startsWithPixels = !bmp.isNull();
3176850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    if (startsWithPixels) {
3186850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                        fillBitmap(&bmp);
3196850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    }
320c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
3216850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    bool success =
3226850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                        canvas.readPixels(&bmp, srcRect.fLeft,
3236850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                                          srcRect.fTop, config8888);
324c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
3256850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    // non-native not implemented on GPU yet
3266850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    bool expectSuccess =
3276850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                        SkIRect::Intersects(srcRect, DEV_RECT) &&
3286850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                        !(1 == dtype &&
3296850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                          config8888 != SkCanvas::kNative_Premul_Config8888);
330c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
3316850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    // determine whether we expected the read to succeed.
3326850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    REPORTER_ASSERT(reporter, success == expectSuccess);
333c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
3346850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    if (success || startsWithPixels) {
3356850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                        checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop,
3366850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                                  success, startsWithPixels, config8888);
3376850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    } else {
3386850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                        // if we had no pixels beforehand and the readPixels
3396850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                        // failed then our bitmap should still not have pixels
3406850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                        REPORTER_ASSERT(reporter, bmp.isNull());
3416850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    }
3426850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                }
3436850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                // check the old webkit version of readPixels that clips the
3446850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                // bitmap size
345c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                SkBitmap wkbmp;
3466850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                bool success = canvas.readPixels(srcRect, &wkbmp);
347c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                SkIRect clippedRect = DEV_RECT;
348c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                if (clippedRect.intersect(srcRect)) {
349c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                    REPORTER_ASSERT(reporter, success);
3506850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    checkRead(reporter, wkbmp, clippedRect.fLeft,
3516850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                              clippedRect.fTop, true, false,
3526850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                              SkCanvas::kNative_Premul_Config8888);
353c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                } else {
354c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                    REPORTER_ASSERT(reporter, !success);
355c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                }
356c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            }
357c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        }
358c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
359c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
360c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
361c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
362c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "TestClassDef.h"
363c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comDEFINE_GPUTESTCLASS("ReadPixels", ReadPixelsTestClass, ReadPixelsTest)
364c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
365