1c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com/*
2c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * Copyright 2011 Google Inc.
3c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com *
4c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
5c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com * found in the LICENSE file.
6c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com */
7c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
873672254a3e498081967d00d27b17ada443e2ab2robertphillips@google.com#include "SkBitmapDevice.h"
9c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "SkCanvas.h"
10cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#include "SkColorPriv.h"
114b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h"
12c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com#include "SkRegion.h"
1352d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed#include "SkSurface.h"
144ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "Test.h"
154ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org
16cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
1767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#include "GrContextFactory.h"
188f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkGpuDevice.h"
19cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
20c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
21c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comstatic const int DEV_W = 100, DEV_H = 100;
22c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comstatic const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);
23d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comstatic const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1,
24c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                                                DEV_H * SK_Scalar1);
25c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
26ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic SkPMColor 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
55ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic SkPMColor getBitmapColor(int x, int y, int w) {
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
64a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgstatic SkPMColor convertToPMColor(SkColorType ct, SkAlphaType at, const uint32_t* addr,
65a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                                  bool* doUnpremul) {
66a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    *doUnpremul = (kUnpremul_SkAlphaType == at);
67a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
68a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const uint8_t* c = reinterpret_cast<const uint8_t*>(addr);
696850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    U8CPU a,r,g,b;
70a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    switch (ct) {
71a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        case kBGRA_8888_SkColorType:
726850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            b = static_cast<U8CPU>(c[0]);
73a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            g = static_cast<U8CPU>(c[1]);
74a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            r = static_cast<U8CPU>(c[2]);
756850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            a = static_cast<U8CPU>(c[3]);
76a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            break;
77a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        case kRGBA_8888_SkColorType:
786850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            r = static_cast<U8CPU>(c[0]);
796850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            g = static_cast<U8CPU>(c[1]);
806850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            b = static_cast<U8CPU>(c[2]);
81a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            a = static_cast<U8CPU>(c[3]);
826850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            break;
83ccaa002dd81a6a8bd5acb7a2fa69a2437873c1fdbsalomon@google.com        default:
84a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            SkDEBUGFAIL("Unexpected colortype");
85ccaa002dd81a6a8bd5acb7a2fa69a2437873c1fdbsalomon@google.com            return 0;
866850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    }
87a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
88a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (*doUnpremul) {
896850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        r = SkMulDiv255Ceiling(r, a);
906850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        g = SkMulDiv255Ceiling(g, a);
916850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com        b = SkMulDiv255Ceiling(b, a);
926850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    }
936850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    return SkPackARGB32(a, r, g, b);
946850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com}
956850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com
96ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic void fillCanvas(SkCanvas* canvas) {
97c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    static SkBitmap bmp;
98c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    if (bmp.isNull()) {
99848250415eddc54075f7eb8795e8db79e749c6abreed        bmp.allocN32Pixels(DEV_W, DEV_H);
100c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels());
101c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        for (int y = 0; y < DEV_H; ++y) {
102c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            for (int x = 0; x < DEV_W; ++x) {
103c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel());
104c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                *pixel = getCanvasColor(x, y);
105c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            }
106c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        }
107c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
108c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    canvas->save();
109c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    canvas->setMatrix(SkMatrix::I());
110c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    canvas->clipRect(DEV_RECT_S, SkRegion::kReplace_Op);
111c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkPaint paint;
112c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
113c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    canvas->drawBitmap(bmp, 0, 0, &paint);
114c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    canvas->restore();
115c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
116d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
117ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic void fillBitmap(SkBitmap* bitmap) {
118c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkASSERT(bitmap->lockPixelsAreWritable());
119c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkAutoLockPixels alp(*bitmap);
120c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int w = bitmap->width();
121c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int h = bitmap->height();
122c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels());
123c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    for (int y = 0; y < h; ++y) {
124c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        for (int x = 0; x < w; ++x) {
125c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel());
12654f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.com            *pixel = getBitmapColor(x, y, w);
127c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        }
128c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
129c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
130c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
131ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic bool checkPixel(SkPMColor a, SkPMColor b, bool didPremulConversion) {
132c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    if (!didPremulConversion) {
133c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        return a == b;
134c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
135c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    int32_t aA = static_cast<int32_t>(SkGetPackedA32(a));
136c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    int32_t aR = static_cast<int32_t>(SkGetPackedR32(a));
137c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    int32_t aG = static_cast<int32_t>(SkGetPackedG32(a));
138c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    int32_t aB = SkGetPackedB32(a);
139c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
140c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    int32_t bA = static_cast<int32_t>(SkGetPackedA32(b));
141c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    int32_t bR = static_cast<int32_t>(SkGetPackedR32(b));
142c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    int32_t bG = static_cast<int32_t>(SkGetPackedG32(b));
143c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    int32_t bB = static_cast<int32_t>(SkGetPackedB32(b));
144c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
145c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    return aA == bA &&
146c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com           SkAbs32(aR - bR) <= 1 &&
147c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com           SkAbs32(aG - bG) <= 1 &&
148c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com           SkAbs32(aB - bB) <= 1;
149c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com}
150c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
151c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// checks the bitmap contains correct pixels after the readPixels
152c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// if the bitmap was prefilled with pixels it checks that these weren't
153c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com// overwritten in the area outside the readPixels.
154ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic bool checkRead(skiatest::Reporter* reporter,
155ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.org                      const SkBitmap& bitmap,
156ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.org                      int x, int y,
157ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.org                      bool checkCanvasPixels,
158a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                      bool checkBitmapPixels) {
159a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkASSERT(4 == bitmap.bytesPerPixel());
160c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkASSERT(!bitmap.isNull());
1616850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    SkASSERT(checkCanvasPixels || checkBitmapPixels);
162d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
163a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkColorType ct = bitmap.colorType();
164a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkAlphaType at = bitmap.alphaType();
165a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
166c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int bw = bitmap.width();
167c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int bh = bitmap.height();
168c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
169c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh);
170c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkIRect clippedSrcRect = DEV_RECT;
171c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    if (!clippedSrcRect.intersect(srcRect)) {
172c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        clippedSrcRect.setEmpty();
173c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
174c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkAutoLockPixels alp(bitmap);
175c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    for (int by = 0; by < bh; ++by) {
176c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        for (int bx = 0; bx < bw; ++bx) {
177c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            int devx = bx + srcRect.fLeft;
178c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            int devy = by + srcRect.fTop;
179d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
180a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            const uint32_t* pixel = bitmap.getAddr32(bx, by);
181c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
182c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            if (clippedSrcRect.contains(devx, devy)) {
1836850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                if (checkCanvasPixels) {
1846850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    SkPMColor canvasPixel = getCanvasColor(devx, devy);
185c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                    bool didPremul;
186a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                    SkPMColor pmPixel = convertToPMColor(ct, at, pixel, &didPremul);
187c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                    bool check;
188c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                    REPORTER_ASSERT(reporter, check = checkPixel(pmPixel, canvasPixel, didPremul));
189c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                    if (!check) {
19072f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                        return false;
1916850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    }
192c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                }
1936850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com            } else if (checkBitmapPixels) {
194a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                REPORTER_ASSERT(reporter, getBitmapColor(bx, by, bw) == *pixel);
195a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                if (getBitmapColor(bx, by, bw) != *pixel) {
19672f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                    return false;
197c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                }
198c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            }
199c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        }
200c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
20172f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com    return true;
202c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
203c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
204c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.comenum BitmapInit {
205c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    kFirstBitmapInit = 0,
206d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
207c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    kNoPixels_BitmapInit = kFirstBitmapInit,
208c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    kTight_BitmapInit,
209c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    kRowBytes_BitmapInit,
210d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
211c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    kBitmapInitCnt
212c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com};
213c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
214ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic BitmapInit nextBMI(BitmapInit bmi) {
215c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    int x = bmi;
216c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    return static_cast<BitmapInit>(++x);
217c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
218c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
219a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgstatic void init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init, SkColorType ct,
220a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                        SkAlphaType at) {
221a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), ct, at);
222fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    size_t rowBytes = 0;
223c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    bool alloc = true;
224c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    switch (init) {
225c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        case kNoPixels_BitmapInit:
226c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            alloc = false;
227c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        case kTight_BitmapInit:
228c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            break;
229c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        case kRowBytes_BitmapInit:
230fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org            rowBytes = (info.width() + 16) * sizeof(SkPMColor);
231c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            break;
232c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        default:
233c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            SkASSERT(0);
234c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            break;
235c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
23602d6f546161e2c98d69066373cec3f54f3c46252skia.committer@gmail.com
237c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    if (alloc) {
238fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org        bitmap->allocPixels(info);
239fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    } else {
240a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        bitmap->setInfo(info, rowBytes);
241c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
242c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
243c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
2444ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.orgDEF_GPUTEST(ReadPixels, reporter, factory) {
245c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    const SkIRect testRects[] = {
246c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // entire thing
247c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        DEV_RECT,
248c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // larger on all sides
249c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10),
250c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // fully contained
251c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4),
252c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // outside top left
253c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, -1, -1),
254c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching top left corner
255c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, 0, 0),
256c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping top left corner
257c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H / 4),
258c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping top left and top right corners
259c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, DEV_H / 4),
260c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching entire top edge
261c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, 0),
262c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping top right corner
263c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W  + 10, DEV_H / 4),
264c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // contained in x, overlapping top edge
265c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(DEV_W / 4, -10, 3 * DEV_W  / 4, DEV_H / 4),
266c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // outside top right corner
267c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(DEV_W + 1, -10, DEV_W + 10, -1),
268c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching top right corner
269c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(DEV_W, -10, DEV_W + 10, 0),
270c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping top left and bottom left corners
271c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H + 10),
272c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching entire left edge
273c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, -10, 0, DEV_H + 10),
274c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping bottom left corner
275c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W / 4, DEV_H + 10),
276c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // contained in y, overlapping left edge
277c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H / 4, DEV_W / 4, 3 * DEV_H / 4),
278c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // outside bottom left corner
279c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H + 1, -1, DEV_H + 10),
280c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching bottom left corner
281c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H, 0, DEV_H + 10),
282c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping bottom left and bottom right corners
283c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
284c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // touching entire left edge
285c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(0, DEV_H, DEV_W, DEV_H + 10),
286c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping bottom right corner
287c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
288c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        // overlapping top right and bottom right corners
289c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H + 10),
290c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    };
291c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
2923cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    for (int dtype = 0; dtype < 3; ++dtype) {
29367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        int glCtxTypeCnt = 1;
29467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#if SK_SUPPORT_GPU
29567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        if (0 != dtype)  {
29667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
29767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        }
29867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#endif
29952d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed        const SkImageInfo info = SkImageInfo::MakeN32Premul(DEV_W, DEV_H);
30067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
30152d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed            SkAutoTUnref<SkSurface> surface;
30267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            if (0 == dtype) {
30352d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed                surface.reset(SkSurface::NewRaster(info));
30467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            } else {
30567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#if SK_SUPPORT_GPU
30667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                GrContextFactory::GLContextType type =
30767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    static_cast<GrContextFactory::GLContextType>(glCtxType);
30867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                if (!GrContextFactory::IsRenderingGLContext(type)) {
30967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    continue;
31067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                }
31167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                GrContext* context = factory->get(type);
31267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                if (NULL == context) {
31367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    continue;
31467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                }
3153cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                GrTextureDesc desc;
3163cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
3173cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                desc.fWidth = DEV_W;
3183cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                desc.fHeight = DEV_H;
319fec0bc3fc13481f5bcb341ab2d2d695911f39bd4bsalomon@google.com                desc.fConfig = kSkia8888_GrPixelConfig;
32052d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed                desc.fOrigin = 1 == dtype ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
3213cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                GrAutoScratchTexture ast(context, desc, GrContext::kExact_ScratchTexMatch);
3223cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                SkAutoTUnref<GrTexture> tex(ast.detach());
32352d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed                surface.reset(SkSurface::NewRenderTargetDirect(tex->asRenderTarget()));
324cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
32567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                continue;
326cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
32767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            }
32852d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed            SkCanvas& canvas = *surface->getCanvas();
32967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            fillCanvas(&canvas);
330c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
331a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            static const struct {
332a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                SkColorType fColorType;
333a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                SkAlphaType fAlphaType;
334a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            } gReadConfigs[] = {
335a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                { kRGBA_8888_SkColorType,   kPremul_SkAlphaType },
336a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                { kRGBA_8888_SkColorType,   kUnpremul_SkAlphaType },
337a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                { kBGRA_8888_SkColorType,   kPremul_SkAlphaType },
338a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                { kBGRA_8888_SkColorType,   kUnpremul_SkAlphaType },
33967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            };
34067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            for (size_t rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) {
34167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                const SkIRect& srcRect = testRects[rect];
342a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                for (BitmapInit bmi = kFirstBitmapInit; bmi < kBitmapInitCnt; bmi = nextBMI(bmi)) {
34367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    for (size_t c = 0; c < SK_ARRAY_COUNT(gReadConfigs); ++c) {
34467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        SkBitmap bmp;
345a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                        init_bitmap(&bmp, srcRect, bmi,
346a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                                    gReadConfigs[c].fColorType, gReadConfigs[c].fAlphaType);
34767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com
34867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        // if the bitmap has pixels allocated before the readPixels,
34967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        // note that and fill them with pattern
35067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        bool startsWithPixels = !bmp.isNull();
35167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        if (startsWithPixels) {
35267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                            fillBitmap(&bmp);
35367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        }
35452d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed                        uint32_t idBefore = surface->generationID();
355a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                        bool success = canvas.readPixels(&bmp, srcRect.fLeft, srcRect.fTop);
35652d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed                        uint32_t idAfter = surface->generationID();
35767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com
35867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        // we expect to succeed when the read isn't fully clipped
35967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        // out.
36067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RECT);
36167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        // determine whether we expected the read to succeed.
36267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        REPORTER_ASSERT(reporter, success == expectSuccess);
36367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        // read pixels should never change the gen id
36467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        REPORTER_ASSERT(reporter, idBefore == idAfter);
36567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com
36667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        if (success || startsWithPixels) {
36767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                            checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop,
368a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                                      success, startsWithPixels);
36967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        } else {
37067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                            // if we had no pixels beforehand and the readPixels
37167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                            // failed then our bitmap should still not have pixels
37267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                            REPORTER_ASSERT(reporter, bmp.isNull());
37367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        }
3746850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    }
37567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    // check the old webkit version of readPixels that clips the
37667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    // bitmap size
37767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    SkBitmap wkbmp;
37867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    bool success = canvas.readPixels(srcRect, &wkbmp);
37967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    SkIRect clippedRect = DEV_RECT;
38067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    if (clippedRect.intersect(srcRect)) {
38167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        REPORTER_ASSERT(reporter, success);
38228fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org                        REPORTER_ASSERT(reporter, kN32_SkColorType == wkbmp.colorType());
383a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                        REPORTER_ASSERT(reporter, kPremul_SkAlphaType == wkbmp.alphaType());
38467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        checkRead(reporter, wkbmp, clippedRect.fLeft,
385a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                                  clippedRect.fTop, true, false);
3866850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    } else {
38767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        REPORTER_ASSERT(reporter, !success);
3886850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                    }
3896850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                }
390c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com            }
391c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        }
392c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
393c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com}
394