WritePixelsTest.cpp revision 61c9b835d13e1d4225f3a04f045658f62c702294
1d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com/*
2d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com * Copyright 2011 Google Inc.
3d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com *
4d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
5d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com * found in the LICENSE file.
6d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com */
7d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
86323ca5ca5f0bc40fc6fdf421e18b55cceb45fe6robertphillips@google.com#include "SkBitmapDevice.h"
9d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com#include "SkCanvas.h"
10cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#include "SkColorPriv.h"
114b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h"
12d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com#include "SkRegion.h"
134ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "Test.h"
144cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org#include "sk_tool_utils.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#else
20cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.comclass GrContext;
2167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.comclass GrContextFactory;
22cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
23d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
24d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comstatic const int DEV_W = 100, DEV_H = 100;
25d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comstatic const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);
26d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comstatic const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1,
27d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                                                DEV_H * SK_Scalar1);
28d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comstatic const U8CPU DEV_PAD = 0xee;
29d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
30ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic SkPMColor getCanvasColor(int x, int y) {
31d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkASSERT(x >= 0 && x < DEV_W);
32d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkASSERT(y >= 0 && y < DEV_H);
33d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
34d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU r = x;
35d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU g = y;
36d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU b = 0xc;
37d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
3831648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com    U8CPU a = 0x0;
39d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    switch ((x+y) % 5) {
40d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 0:
41d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0xff;
42d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
43d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 1:
44d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x80;
45d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
46d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 2:
47d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0xCC;
48d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
49d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 3:
50d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x00;
51d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
5231648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com        case 4:
5331648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com            a = 0x01;
5431648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com            break;
55d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
56d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return SkPremultiplyARGBInline(a, r, g, b);
57d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
58d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
59180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.comstatic bool config8888IsPremul(SkCanvas::Config8888 config8888) {
60180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    switch (config8888) {
61180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kNative_Premul_Config8888:
62180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kBGRA_Premul_Config8888:
63180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kRGBA_Premul_Config8888:
64180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            return true;
65180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kNative_Unpremul_Config8888:
66180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kBGRA_Unpremul_Config8888:
67180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kRGBA_Unpremul_Config8888:
68180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            return false;
69180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        default:
70180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            SkASSERT(0);
71180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            return false;
72180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    }
73180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com}
74180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com
75d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com// assumes any premu/.unpremul has been applied
76180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.comstatic uint32_t packConfig8888(SkCanvas::Config8888 config8888,
77180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                               U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
78d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    uint32_t r32;
79d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    uint8_t* result = reinterpret_cast<uint8_t*>(&r32);
80180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    switch (config8888) {
81180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kNative_Premul_Config8888:
82180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kNative_Unpremul_Config8888:
83180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            r32 = SkPackARGB32NoCheck(a, r, g, b);
84180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            break;
85180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kBGRA_Premul_Config8888:
86180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kBGRA_Unpremul_Config8888:
87d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[0] = b;
88d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[1] = g;
89d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[2] = r;
90d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[3] = a;
91d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
92180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kRGBA_Premul_Config8888:
93180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kRGBA_Unpremul_Config8888:
94d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[0] = r;
95d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[1] = g;
96d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[2] = b;
97d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[3] = a;
98d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
99d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        default:
100d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            SkASSERT(0);
101d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            return 0;
102d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
103d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return r32;
104d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
105d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
106180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.comstatic uint32_t getBitmapColor(int x, int y, int w, SkCanvas::Config8888 config8888) {
107d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int n = y * w + x;
108d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU b = n & 0xff;
109d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU g = (n >> 8) & 0xff;
110d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU r = (n >> 16) & 0xff;
11131648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com    U8CPU a = 0;
112d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    switch ((x+y) % 5) {
113d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 4:
114d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0xff;
115d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
116d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 3:
117d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x80;
118d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
119d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 2:
120d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0xCC;
121d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
122d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 1:
123d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x01;
124d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
125d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 0:
126d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x00;
127d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
128d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
129180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    if (config8888IsPremul(config8888)) {
130d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        r = SkMulDiv255Ceiling(r, a);
131d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        g = SkMulDiv255Ceiling(g, a);
132d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        b = SkMulDiv255Ceiling(b, a);
133d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
134180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    return packConfig8888(config8888, a, r, g , b);
135d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
136d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
137ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic void fillCanvas(SkCanvas* canvas) {
1384cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBitmap bmp;
139d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    if (bmp.isNull()) {
140fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org        SkDEBUGCODE(bool alloc = ) bmp.allocN32Pixels(DEV_W, DEV_H);
141d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkASSERT(alloc);
142d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        for (int y = 0; y < DEV_H; ++y) {
143d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            for (int x = 0; x < DEV_W; ++x) {
1444cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                *bmp.getAddr32(x, y) = getCanvasColor(x, y);
145d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
146d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
147d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
148d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->save();
149d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->setMatrix(SkMatrix::I());
150d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->clipRect(DEV_RECT_S, SkRegion::kReplace_Op);
151d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkPaint paint;
152d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
153d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->drawBitmap(bmp, 0, 0, &paint);
154d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->restore();
155d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
156d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
157180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.comstatic SkPMColor convertConfig8888ToPMColor(SkCanvas::Config8888 config8888,
158180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                                            uint32_t color,
159180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                                            bool* premul) {
160180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    const uint8_t* c = reinterpret_cast<uint8_t*>(&color);
161180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    U8CPU a,r,g,b;
162180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    *premul = false;
163180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    switch (config8888) {
164180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kNative_Premul_Config8888:
165180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            return color;
166180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kNative_Unpremul_Config8888:
167180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            *premul = true;
168180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            a = SkGetPackedA32(color);
169180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            r = SkGetPackedR32(color);
170180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            g = SkGetPackedG32(color);
171180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            b = SkGetPackedB32(color);
172d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
173180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kBGRA_Unpremul_Config8888:
174180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            *premul = true; // fallthru
175180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kBGRA_Premul_Config8888:
176180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            a = static_cast<U8CPU>(c[3]);
177180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            r = static_cast<U8CPU>(c[2]);
178180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            g = static_cast<U8CPU>(c[1]);
179180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            b = static_cast<U8CPU>(c[0]);
180d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
181180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kRGBA_Unpremul_Config8888:
182180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            *premul = true; // fallthru
183180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        case SkCanvas::kRGBA_Premul_Config8888:
184180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            a = static_cast<U8CPU>(c[3]);
185180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            r = static_cast<U8CPU>(c[0]);
186180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            g = static_cast<U8CPU>(c[1]);
187180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            b = static_cast<U8CPU>(c[2]);
188e14792d99fc7a1a314ef5e2ca5b269239468355acommit-bot@chromium.org            break;
189180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        default:
190180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            SkDEBUGFAIL("Unexpected Config8888");
191180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            return 0;
192d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
193180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    if (*premul) {
194180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        r = SkMulDiv255Ceiling(r, a);
195180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        g = SkMulDiv255Ceiling(g, a);
196180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        b = SkMulDiv255Ceiling(b, a);
197180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    }
198180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    return SkPackARGB32(a, r, g, b);
199d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
200d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
201ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic bool checkPixel(SkPMColor a, SkPMColor b, bool didPremulConversion) {
202d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    if (!didPremulConversion) {
203d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return a == b;
204d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
205d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aA = static_cast<int32_t>(SkGetPackedA32(a));
206d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aR = static_cast<int32_t>(SkGetPackedR32(a));
207d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aG = static_cast<int32_t>(SkGetPackedG32(a));
208d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aB = SkGetPackedB32(a);
209d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
210d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bA = static_cast<int32_t>(SkGetPackedA32(b));
211d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bR = static_cast<int32_t>(SkGetPackedR32(b));
212d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bG = static_cast<int32_t>(SkGetPackedG32(b));
213d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bB = static_cast<int32_t>(SkGetPackedB32(b));
214d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
215d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return aA == bA &&
216d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com           SkAbs32(aR - bR) <= 1 &&
217d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com           SkAbs32(aG - bG) <= 1 &&
218d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com           SkAbs32(aB - bB) <= 1;
219d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
220d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
221180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.comstatic bool checkWrite(skiatest::Reporter* reporter,
222180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                       SkCanvas* canvas,
223180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                       const SkBitmap& bitmap,
224180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                       int writeX, int writeY,
225180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                       SkCanvas::Config8888 config8888) {
226180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    SkBaseDevice* dev = canvas->getDevice();
227180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    if (!dev) {
228d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return false;
229d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
230180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    SkBitmap devBmp = dev->accessBitmap(false);
231180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    if (devBmp.width() != DEV_W ||
232180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        devBmp.height() != DEV_H ||
233180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        devBmp.config() != SkBitmap::kARGB_8888_Config ||
234180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        devBmp.isNull()) {
235d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return false;
236d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
237180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    SkAutoLockPixels alp(devBmp);
238d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
239180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    intptr_t canvasPixels = reinterpret_cast<intptr_t>(devBmp.getPixels());
240180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    size_t canvasRowBytes = devBmp.rowBytes();
241d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkIRect writeRect = SkIRect::MakeXYWH(writeX, writeY, bitmap.width(), bitmap.height());
242d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    for (int cy = 0; cy < DEV_H; ++cy) {
243180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        const SkPMColor* canvasRow = reinterpret_cast<const SkPMColor*>(canvasPixels);
244d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        for (int cx = 0; cx < DEV_W; ++cx) {
245180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            SkPMColor canvasPixel = canvasRow[cx];
246d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            if (writeRect.contains(cx, cy)) {
247d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                int bx = cx - writeX;
248d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                int by = cy - writeY;
249180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                uint32_t bmpColor8888 = getBitmapColor(bx, by, bitmap.width(), config8888);
250180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                bool mul;
251180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                SkPMColor bmpPMColor = convertConfig8888ToPMColor(config8888, bmpColor8888, &mul);
252180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                bool check;
253180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                REPORTER_ASSERT(reporter, check = checkPixel(bmpPMColor, canvasPixel, mul));
254d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                if (!check) {
25572f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                    return false;
256d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
257d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            } else {
258d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                bool check;
259d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                SkPMColor testColor = getCanvasColor(cx, cy);
260d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                REPORTER_ASSERT(reporter, check = (canvasPixel == testColor));
261d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                if (!check) {
26272f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                    return false;
263d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
264d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
265d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
266d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        if (cy != DEV_H -1) {
267180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            const char* pad = reinterpret_cast<const char*>(canvasPixels + 4 * DEV_W);
268d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            for (size_t px = 0; px < canvasRowBytes - 4 * DEV_W; ++px) {
269d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                bool check;
270d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                REPORTER_ASSERT(reporter, check = (pad[px] == static_cast<char>(DEV_PAD)));
271d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                if (!check) {
27272f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                    return false;
273d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
274d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
275d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
276180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com        canvasPixels += canvasRowBytes;
277d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
278d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
27972f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com    return true;
280d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
281d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
282d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comenum DevType {
283d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    kRaster_DevType,
284cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
2853cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    kGpu_BottomLeft_DevType,
2863cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    kGpu_TopLeft_DevType,
287cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
288d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com};
289d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
290d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comstruct CanvasConfig {
291d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    DevType fDevType;
292d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    bool fTightRowBytes;
293d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com};
294d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
295d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comstatic const CanvasConfig gCanvasConfigs[] = {
296d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    {kRaster_DevType, true},
297d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    {kRaster_DevType, false},
2988f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com#if SK_SUPPORT_GPU
2993cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    {kGpu_BottomLeft_DevType, true}, // row bytes has no meaning on gpu devices
3003cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    {kGpu_TopLeft_DevType, true}, // row bytes has no meaning on gpu devices
301bbce8b29bd0d30ee0b1155ae72023e779cbdce9bbsalomon@google.com#endif
302d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com};
303d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
304fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org#include "SkMallocPixelRef.h"
305fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org
306fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org// This is a tricky pattern, because we have to setConfig+rowBytes AND specify
307fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org// a custom pixelRef (which also has to specify its rowBytes), so we have to be
308fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org// sure that the two rowBytes match (and the infos match).
309fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org//
310fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.orgstatic bool allocRowBytes(SkBitmap* bm, const SkImageInfo& info, size_t rowBytes) {
311fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    if (!bm->setConfig(info, rowBytes)) {
312fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org        return false;
313fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    }
314fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, rowBytes, NULL);
315fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    bm->setPixelRef(pr)->unref();
316fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    return true;
317fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org}
318fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org
319ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic SkBaseDevice* createDevice(const CanvasConfig& c, GrContext* grCtx) {
320d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    switch (c.fDevType) {
321d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case kRaster_DevType: {
322d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            SkBitmap bmp;
323d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            size_t rowBytes = c.fTightRowBytes ? 0 : 4 * DEV_W + 100;
324fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org            SkImageInfo info = SkImageInfo::MakeN32Premul(DEV_W, DEV_H);
325fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org            if (!allocRowBytes(&bmp, info, rowBytes)) {
32644a42ea8b22a845a419b8ae3b47c4619fdec0215reed@google.com                sk_throw();
32744a42ea8b22a845a419b8ae3b47c4619fdec0215reed@google.com                return NULL;
328d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
329d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            // if rowBytes isn't tight then set the padding to a known value
330d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            if (rowBytes) {
331d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                SkAutoLockPixels alp(bmp);
33261c9b835d13e1d4225f3a04f045658f62c702294commit-bot@chromium.org                // We'd just use memset here but GCC 4.8.1 throws up a bogus warning when we do.
33361c9b835d13e1d4225f3a04f045658f62c702294commit-bot@chromium.org                for (size_t i = 0; i < bmp.getSafeSize(); i++) {
33461c9b835d13e1d4225f3a04f045658f62c702294commit-bot@chromium.org                    ((uint8_t*)bmp.getPixels())[i] = DEV_PAD;
33561c9b835d13e1d4225f3a04f045658f62c702294commit-bot@chromium.org                }
336d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
3371f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com            return new SkBitmapDevice(bmp);
338cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        }
339cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
3403cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        case kGpu_BottomLeft_DevType:
3413cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        case kGpu_TopLeft_DevType:
3423cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            GrTextureDesc desc;
3433cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            desc.fFlags = kRenderTarget_GrTextureFlagBit;
3443cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            desc.fWidth = DEV_W;
3453cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            desc.fHeight = DEV_H;
346fec0bc3fc13481f5bcb341ab2d2d695911f39bd4bsalomon@google.com            desc.fConfig = kSkia8888_GrPixelConfig;
3473cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            desc.fOrigin = kGpu_TopLeft_DevType == c.fDevType ?
3483cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
3493cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            GrAutoScratchTexture ast(grCtx, desc, GrContext::kExact_ScratchTexMatch);
3503cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            SkAutoTUnref<GrTexture> tex(ast.detach());
3513cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            return new SkGpuDevice(grCtx, tex);
352cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
353d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
35444a42ea8b22a845a419b8ae3b47c4619fdec0215reed@google.com    return NULL;
355d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
356d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
357180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.comstatic bool setupBitmap(SkBitmap* bitmap,
358180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                        SkCanvas::Config8888 config8888,
359180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                        int w, int h,
360180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                        bool tightRowBytes) {
361180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    size_t rowBytes = tightRowBytes ? 0 : 4 * w + 60;
362180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);
363180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    if (!allocRowBytes(bitmap, info, rowBytes)) {
364d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return false;
365d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
366180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    SkAutoLockPixels alp(*bitmap);
367180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com    intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels());
368d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    for (int y = 0; y < h; ++y) {
369d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        for (int x = 0; x < w; ++x) {
370180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            uint32_t* pixel = reinterpret_cast<uint32_t*>(pixels + y * bitmap->rowBytes() + x * 4);
371180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            *pixel = getBitmapColor(x, y, w, config8888);
372d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
373d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
374d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return true;
375d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
376d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
3774ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.orgDEF_GPUTEST(WritePixels, reporter, factory) {
378d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkCanvas canvas;
379d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
380d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    const SkIRect testRects[] = {
381d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // entire thing
382d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        DEV_RECT,
383d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // larger on all sides
384d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10),
385d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // fully contained
386d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4),
387d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // outside top left
388d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, -1, -1),
389d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching top left corner
390d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, 0, 0),
391d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top left corner
392d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H / 4),
393d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top left and top right corners
394d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, DEV_H / 4),
395d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching entire top edge
396d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, 0),
397d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top right corner
398d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W  + 10, DEV_H / 4),
399d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // contained in x, overlapping top edge
400d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W / 4, -10, 3 * DEV_W  / 4, DEV_H / 4),
401d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // outside top right corner
402d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W + 1, -10, DEV_W + 10, -1),
403d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching top right corner
404d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W, -10, DEV_W + 10, 0),
405d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top left and bottom left corners
406d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H + 10),
407d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching entire left edge
408d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, 0, DEV_H + 10),
409d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping bottom left corner
410d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W / 4, DEV_H + 10),
411d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // contained in y, overlapping left edge
412d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H / 4, DEV_W / 4, 3 * DEV_H / 4),
413d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // outside bottom left corner
414d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H + 1, -1, DEV_H + 10),
415d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching bottom left corner
416d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H, 0, DEV_H + 10),
417d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping bottom left and bottom right corners
418d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
419d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching entire left edge
420d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(0, DEV_H, DEV_W, DEV_H + 10),
421d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping bottom right corner
422d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
423d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top right and bottom right corners
424d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H + 10),
425d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    };
426d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
427d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gCanvasConfigs); ++i) {
42867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        int glCtxTypeCnt = 1;
42967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#if SK_SUPPORT_GPU
4303cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        bool isGPUDevice = kGpu_TopLeft_DevType == gCanvasConfigs[i].fDevType ||
4313cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                           kGpu_BottomLeft_DevType == gCanvasConfigs[i].fDevType;
4323cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        if (isGPUDevice) {
43367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
43467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        }
43567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#endif
43667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
43767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            GrContext* context = NULL;
43867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#if SK_SUPPORT_GPU
4393cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            if (isGPUDevice) {
44067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                GrContextFactory::GLContextType type =
44167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    static_cast<GrContextFactory::GLContextType>(glCtxType);
44267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                if (!GrContextFactory::IsRenderingGLContext(type)) {
44367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    continue;
44467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                }
44567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                context = factory->get(type);
44667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                if (NULL == context) {
44767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    continue;
44867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                }
44967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            }
45067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#endif
45167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com
4521f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com            SkAutoTUnref<SkBaseDevice> device(createDevice(gCanvasConfigs[i], context));
45367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            SkCanvas canvas(device);
454d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
455180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com            static const SkCanvas::Config8888 gSrcConfigs[] = {
456180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                SkCanvas::kNative_Premul_Config8888,
457180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                SkCanvas::kNative_Unpremul_Config8888,
458180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                SkCanvas::kBGRA_Premul_Config8888,
459180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                SkCanvas::kBGRA_Unpremul_Config8888,
460180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                SkCanvas::kRGBA_Premul_Config8888,
461180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                SkCanvas::kRGBA_Unpremul_Config8888,
46267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            };
46367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            for (size_t r = 0; r < SK_ARRAY_COUNT(testRects); ++r) {
46467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                const SkIRect& rect = testRects[r];
46567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                for (int tightBmp = 0; tightBmp < 2; ++tightBmp) {
46667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    for (size_t c = 0; c < SK_ARRAY_COUNT(gSrcConfigs); ++c) {
46767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        fillCanvas(&canvas);
468180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                        SkCanvas::Config8888 config8888 = gSrcConfigs[c];
46967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        SkBitmap bmp;
470180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                        REPORTER_ASSERT(reporter, setupBitmap(&bmp, config8888, rect.width(), rect.height(), SkToBool(tightBmp)));
47167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        uint32_t idBefore = canvas.getDevice()->accessBitmap(false).getGenerationID();
4724cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
473180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                        SkColorType ct;
474180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                        SkAlphaType at;
475180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                        sk_tool_utils::config8888_to_imagetypes(config8888, &ct, &at);
476180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                        sk_tool_utils::write_pixels(&canvas, bmp, rect.fLeft, rect.fTop, ct, at);
4774cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
47867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        uint32_t idAfter = canvas.getDevice()->accessBitmap(false).getGenerationID();
479180e36abf6e5da1688c9da5ef614a78c471834d5bsalomon@google.com                        REPORTER_ASSERT(reporter, checkWrite(reporter, &canvas, bmp, rect.fLeft, rect.fTop, config8888));
480405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com
48167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        // we should change the genID iff pixels were actually written.
48267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        SkIRect canvasRect = SkIRect::MakeSize(canvas.getDeviceSize());
48367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        SkIRect writeRect = SkIRect::MakeXYWH(rect.fLeft, rect.fTop,
48467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                                                              bmp.width(), bmp.height());
48567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        bool intersects = SkIRect::Intersects(canvasRect, writeRect) ;
48667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        REPORTER_ASSERT(reporter, intersects == (idBefore != idAfter));
48767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    }
488d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
489d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
490d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
491d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
492d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
493