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
59d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com// assumes any premu/.unpremul has been applied
607111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic uint32_t packColorType(SkColorType ct, U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
61d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    uint32_t r32;
62d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    uint8_t* result = reinterpret_cast<uint8_t*>(&r32);
637111d463cee893a479280c7af41757e709e33ef5reed@google.com    switch (ct) {
647111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kBGRA_8888_SkColorType:
65d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[0] = b;
66d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[1] = g;
67d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[2] = r;
68d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[3] = a;
69d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
707111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kRGBA_8888_SkColorType:
71d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[0] = r;
72d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[1] = g;
73d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[2] = b;
74d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[3] = a;
75d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
76d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        default:
77d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            SkASSERT(0);
78d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            return 0;
79d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
80d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return r32;
81d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
82d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
837111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic uint32_t getBitmapColor(int x, int y, int w, SkColorType ct, SkAlphaType at) {
84d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int n = y * w + x;
85d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU b = n & 0xff;
86d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU g = (n >> 8) & 0xff;
87d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU r = (n >> 16) & 0xff;
8831648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com    U8CPU a = 0;
89d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    switch ((x+y) % 5) {
90d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 4:
91d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0xff;
92d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
93d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 3:
94d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x80;
95d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
96d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 2:
97d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0xCC;
98d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
99d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 1:
100d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x01;
101d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
102d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 0:
103d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x00;
104d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
105d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
1067111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (kPremul_SkAlphaType == at) {
107d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        r = SkMulDiv255Ceiling(r, a);
108d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        g = SkMulDiv255Ceiling(g, a);
109d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        b = SkMulDiv255Ceiling(b, a);
110d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
1117111d463cee893a479280c7af41757e709e33ef5reed@google.com    return packColorType(ct, a, r, g , b);
112d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
113d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
114ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic void fillCanvas(SkCanvas* canvas) {
1154cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBitmap bmp;
116d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    if (bmp.isNull()) {
117fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org        SkDEBUGCODE(bool alloc = ) bmp.allocN32Pixels(DEV_W, DEV_H);
118d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkASSERT(alloc);
119d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        for (int y = 0; y < DEV_H; ++y) {
120d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            for (int x = 0; x < DEV_W; ++x) {
1214cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                *bmp.getAddr32(x, y) = getCanvasColor(x, y);
122d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
123d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
124d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
125d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->save();
126d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->setMatrix(SkMatrix::I());
127d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->clipRect(DEV_RECT_S, SkRegion::kReplace_Op);
128d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkPaint paint;
129d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
130d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->drawBitmap(bmp, 0, 0, &paint);
131d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->restore();
132d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
133d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
1347111d463cee893a479280c7af41757e709e33ef5reed@google.com/**
1357111d463cee893a479280c7af41757e709e33ef5reed@google.com *  Lucky for us, alpha is always in the same spot (SK_A32_SHIFT), for both RGBA and BGRA.
1367111d463cee893a479280c7af41757e709e33ef5reed@google.com *  Thus this routine doesn't need to know the exact colortype
1377111d463cee893a479280c7af41757e709e33ef5reed@google.com */
1387111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic uint32_t premul(uint32_t color) {
1397111d463cee893a479280c7af41757e709e33ef5reed@google.com    unsigned a = SkGetPackedA32(color);
1407111d463cee893a479280c7af41757e709e33ef5reed@google.com    // these next three are not necessarily r,g,b in that order, but they are r,g,b in some order.
1417111d463cee893a479280c7af41757e709e33ef5reed@google.com    unsigned c0 = SkGetPackedR32(color);
1427111d463cee893a479280c7af41757e709e33ef5reed@google.com    unsigned c1 = SkGetPackedG32(color);
1437111d463cee893a479280c7af41757e709e33ef5reed@google.com    unsigned c2 = SkGetPackedB32(color);
1447111d463cee893a479280c7af41757e709e33ef5reed@google.com    c0 = SkMulDiv255Ceiling(c0, a);
1457111d463cee893a479280c7af41757e709e33ef5reed@google.com    c1 = SkMulDiv255Ceiling(c1, a);
1467111d463cee893a479280c7af41757e709e33ef5reed@google.com    c2 = SkMulDiv255Ceiling(c2, a);
1477111d463cee893a479280c7af41757e709e33ef5reed@google.com    return SkPackARGB32NoCheck(a, c0, c1, c2);
1487111d463cee893a479280c7af41757e709e33ef5reed@google.com}
1497111d463cee893a479280c7af41757e709e33ef5reed@google.com
1507111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic SkPMColor convert_to_PMColor(SkColorType ct, SkAlphaType at, uint32_t color) {
1517111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (kUnpremul_SkAlphaType == at) {
1527111d463cee893a479280c7af41757e709e33ef5reed@google.com        color = premul(color);
1537111d463cee893a479280c7af41757e709e33ef5reed@google.com    }
1547111d463cee893a479280c7af41757e709e33ef5reed@google.com    switch (ct) {
1557111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kRGBA_8888_SkColorType:
1567111d463cee893a479280c7af41757e709e33ef5reed@google.com            color = SkSwizzle_RGBA_to_PMColor(color);
157e14792d99fc7a1a314ef5e2ca5b269239468355acommit-bot@chromium.org            break;
1587111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kBGRA_8888_SkColorType:
1597111d463cee893a479280c7af41757e709e33ef5reed@google.com            color = SkSwizzle_BGRA_to_PMColor(color);
1601121170477302e25ef2a020cf2092aa6b399b3efreed@google.com            break;
161231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org        default:
1627111d463cee893a479280c7af41757e709e33ef5reed@google.com            SkASSERT(0);
1637111d463cee893a479280c7af41757e709e33ef5reed@google.com            break;
164231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org    }
1657111d463cee893a479280c7af41757e709e33ef5reed@google.com    return color;
166d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
167d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
168ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic bool checkPixel(SkPMColor a, SkPMColor b, bool didPremulConversion) {
169d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    if (!didPremulConversion) {
170d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return a == b;
171d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
172d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aA = static_cast<int32_t>(SkGetPackedA32(a));
173d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aR = static_cast<int32_t>(SkGetPackedR32(a));
174d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aG = static_cast<int32_t>(SkGetPackedG32(a));
175d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aB = SkGetPackedB32(a);
176d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
177d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bA = static_cast<int32_t>(SkGetPackedA32(b));
178d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bR = static_cast<int32_t>(SkGetPackedR32(b));
179d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bG = static_cast<int32_t>(SkGetPackedG32(b));
180d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bB = static_cast<int32_t>(SkGetPackedB32(b));
181d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
182d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return aA == bA &&
183d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com           SkAbs32(aR - bR) <= 1 &&
184d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com           SkAbs32(aG - bG) <= 1 &&
185d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com           SkAbs32(aB - bB) <= 1;
186d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
187d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
1887111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic bool checkWrite(skiatest::Reporter* reporter, SkCanvas* canvas, const SkBitmap& bitmap,
1897111d463cee893a479280c7af41757e709e33ef5reed@google.com                       int writeX, int writeY) {
1907111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkImageInfo canvasInfo;
1917111d463cee893a479280c7af41757e709e33ef5reed@google.com    size_t canvasRowBytes;
1927111d463cee893a479280c7af41757e709e33ef5reed@google.com    const uint32_t* canvasPixels;
1937111d463cee893a479280c7af41757e709e33ef5reed@google.com
1947111d463cee893a479280c7af41757e709e33ef5reed@google.com    // Can't use canvas->peekPixels(), as we are trying to look at GPU pixels sometimes as well.
1957111d463cee893a479280c7af41757e709e33ef5reed@google.com    // At some point this will be unsupported, as we won't allow accessBitmap() to magically call
1967111d463cee893a479280c7af41757e709e33ef5reed@google.com    // readPixels for the client.
1977111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkBitmap secretDevBitmap;
1987111d463cee893a479280c7af41757e709e33ef5reed@google.com    {
1997111d463cee893a479280c7af41757e709e33ef5reed@google.com        SkBaseDevice* dev = canvas->getDevice();
2007111d463cee893a479280c7af41757e709e33ef5reed@google.com        if (!dev) {
2017111d463cee893a479280c7af41757e709e33ef5reed@google.com            return false;
2027111d463cee893a479280c7af41757e709e33ef5reed@google.com        }
2037111d463cee893a479280c7af41757e709e33ef5reed@google.com        secretDevBitmap = dev->accessBitmap(false);
2047111d463cee893a479280c7af41757e709e33ef5reed@google.com    }
2057111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkAutoLockPixels alp(secretDevBitmap);
2067111d463cee893a479280c7af41757e709e33ef5reed@google.com    canvasInfo = secretDevBitmap.info();
2077111d463cee893a479280c7af41757e709e33ef5reed@google.com    canvasRowBytes = secretDevBitmap.rowBytes();
2087111d463cee893a479280c7af41757e709e33ef5reed@google.com    canvasPixels = static_cast<const uint32_t*>(secretDevBitmap.getPixels());
2097111d463cee893a479280c7af41757e709e33ef5reed@google.com
2107111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (NULL == canvasPixels) {
211d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return false;
212d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
2137111d463cee893a479280c7af41757e709e33ef5reed@google.com
2147111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (canvasInfo.width() != DEV_W ||
2157111d463cee893a479280c7af41757e709e33ef5reed@google.com        canvasInfo.height() != DEV_H ||
21628fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        canvasInfo.colorType() != kN32_SkColorType) {
217d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return false;
218d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
219d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
2207111d463cee893a479280c7af41757e709e33ef5reed@google.com    const SkImageInfo bmInfo = bitmap.info();
2217111d463cee893a479280c7af41757e709e33ef5reed@google.com
222d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkIRect writeRect = SkIRect::MakeXYWH(writeX, writeY, bitmap.width(), bitmap.height());
223d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    for (int cy = 0; cy < DEV_H; ++cy) {
224d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        for (int cx = 0; cx < DEV_W; ++cx) {
2257111d463cee893a479280c7af41757e709e33ef5reed@google.com            SkPMColor canvasPixel = canvasPixels[cx];
226d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            if (writeRect.contains(cx, cy)) {
227d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                int bx = cx - writeX;
228d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                int by = cy - writeY;
2297111d463cee893a479280c7af41757e709e33ef5reed@google.com                uint32_t bmpColor8888 = getBitmapColor(bx, by, bitmap.width(),
2307111d463cee893a479280c7af41757e709e33ef5reed@google.com                                                       bmInfo.colorType(), bmInfo.alphaType());
2317111d463cee893a479280c7af41757e709e33ef5reed@google.com                bool mul = (kUnpremul_SkAlphaType == bmInfo.alphaType());
2327111d463cee893a479280c7af41757e709e33ef5reed@google.com                SkPMColor bmpPMColor = convert_to_PMColor(bmInfo.colorType(), bmInfo.alphaType(),
2337111d463cee893a479280c7af41757e709e33ef5reed@google.com                                                          bmpColor8888);
2347111d463cee893a479280c7af41757e709e33ef5reed@google.com                bool check = checkPixel(bmpPMColor, canvasPixel, mul);
2357111d463cee893a479280c7af41757e709e33ef5reed@google.com                REPORTER_ASSERT(reporter, check);
236d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                if (!check) {
23772f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                    return false;
238d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
239d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            } else {
240d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                bool check;
241d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                SkPMColor testColor = getCanvasColor(cx, cy);
242d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                REPORTER_ASSERT(reporter, check = (canvasPixel == testColor));
243d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                if (!check) {
24472f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                    return false;
245d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
246d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
247d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
248d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        if (cy != DEV_H -1) {
2497111d463cee893a479280c7af41757e709e33ef5reed@google.com            const char* pad = reinterpret_cast<const char*>(canvasPixels + DEV_W);
250d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            for (size_t px = 0; px < canvasRowBytes - 4 * DEV_W; ++px) {
251d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                bool check;
252d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                REPORTER_ASSERT(reporter, check = (pad[px] == static_cast<char>(DEV_PAD)));
253d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                if (!check) {
25472f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                    return false;
255d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
256d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
257d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
2587111d463cee893a479280c7af41757e709e33ef5reed@google.com        canvasPixels += canvasRowBytes/4;
259d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
260d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
26172f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com    return true;
262d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
263d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
264d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comenum DevType {
265d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    kRaster_DevType,
266cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
2673cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    kGpu_BottomLeft_DevType,
2683cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    kGpu_TopLeft_DevType,
269cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
270d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com};
271d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
272d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comstruct CanvasConfig {
273d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    DevType fDevType;
274d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    bool fTightRowBytes;
275d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com};
276d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
277d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comstatic const CanvasConfig gCanvasConfigs[] = {
278d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    {kRaster_DevType, true},
279d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    {kRaster_DevType, false},
2808f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com#if SK_SUPPORT_GPU
2813cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    {kGpu_BottomLeft_DevType, true}, // row bytes has no meaning on gpu devices
2823cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    {kGpu_TopLeft_DevType, true}, // row bytes has no meaning on gpu devices
283bbce8b29bd0d30ee0b1155ae72023e779cbdce9bbsalomon@google.com#endif
284d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com};
285d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
286fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org#include "SkMallocPixelRef.h"
287fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org
288fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org// This is a tricky pattern, because we have to setConfig+rowBytes AND specify
289fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org// a custom pixelRef (which also has to specify its rowBytes), so we have to be
290fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org// sure that the two rowBytes match (and the infos match).
291fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org//
292fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.orgstatic bool allocRowBytes(SkBitmap* bm, const SkImageInfo& info, size_t rowBytes) {
293a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    if (!bm->setInfo(info, rowBytes)) {
294fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org        return false;
295fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    }
296fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, rowBytes, NULL);
297fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    bm->setPixelRef(pr)->unref();
298fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    return true;
299fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org}
300fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org
301ddf94cf108ae430877f009bd67b9070341426947commit-bot@chromium.orgstatic SkBaseDevice* createDevice(const CanvasConfig& c, GrContext* grCtx) {
302d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    switch (c.fDevType) {
303d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case kRaster_DevType: {
304d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            SkBitmap bmp;
305d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            size_t rowBytes = c.fTightRowBytes ? 0 : 4 * DEV_W + 100;
306fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org            SkImageInfo info = SkImageInfo::MakeN32Premul(DEV_W, DEV_H);
307fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org            if (!allocRowBytes(&bmp, info, rowBytes)) {
30844a42ea8b22a845a419b8ae3b47c4619fdec0215reed@google.com                sk_throw();
30944a42ea8b22a845a419b8ae3b47c4619fdec0215reed@google.com                return NULL;
310d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
311d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            // if rowBytes isn't tight then set the padding to a known value
312d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            if (rowBytes) {
313d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                SkAutoLockPixels alp(bmp);
31461c9b835d13e1d4225f3a04f045658f62c702294commit-bot@chromium.org                // We'd just use memset here but GCC 4.8.1 throws up a bogus warning when we do.
31561c9b835d13e1d4225f3a04f045658f62c702294commit-bot@chromium.org                for (size_t i = 0; i < bmp.getSafeSize(); i++) {
31661c9b835d13e1d4225f3a04f045658f62c702294commit-bot@chromium.org                    ((uint8_t*)bmp.getPixels())[i] = DEV_PAD;
31761c9b835d13e1d4225f3a04f045658f62c702294commit-bot@chromium.org                }
318d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
3191f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com            return new SkBitmapDevice(bmp);
320cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        }
321cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
3223cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        case kGpu_BottomLeft_DevType:
3233cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        case kGpu_TopLeft_DevType:
3243cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            GrTextureDesc desc;
3253cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            desc.fFlags = kRenderTarget_GrTextureFlagBit;
3263cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            desc.fWidth = DEV_W;
3273cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            desc.fHeight = DEV_H;
328fec0bc3fc13481f5bcb341ab2d2d695911f39bd4bsalomon@google.com            desc.fConfig = kSkia8888_GrPixelConfig;
3293cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            desc.fOrigin = kGpu_TopLeft_DevType == c.fDevType ?
3303cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
3313cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            GrAutoScratchTexture ast(grCtx, desc, GrContext::kExact_ScratchTexMatch);
3323cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            SkAutoTUnref<GrTexture> tex(ast.detach());
3333cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            return new SkGpuDevice(grCtx, tex);
334cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
335d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
33644a42ea8b22a845a419b8ae3b47c4619fdec0215reed@google.com    return NULL;
337d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
338d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
3397111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic bool setupBitmap(SkBitmap* bm, SkColorType ct, SkAlphaType at, int w, int h, int tightRB) {
3407111d463cee893a479280c7af41757e709e33ef5reed@google.com    size_t rowBytes = tightRB ? 0 : 4 * w + 60;
3417111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkImageInfo info = SkImageInfo::Make(w, h, ct, at);
3427111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (!allocRowBytes(bm, info, rowBytes)) {
343d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return false;
344d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
3457111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkAutoLockPixels alp(*bm);
346d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    for (int y = 0; y < h; ++y) {
347d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        for (int x = 0; x < w; ++x) {
3487111d463cee893a479280c7af41757e709e33ef5reed@google.com            *bm->getAddr32(x, y) = getBitmapColor(x, y, w, ct, at);
349d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
350d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
351d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return true;
352d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
353d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
3544ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.orgDEF_GPUTEST(WritePixels, reporter, factory) {
355d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkCanvas canvas;
356d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
357d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    const SkIRect testRects[] = {
358d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // entire thing
359d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        DEV_RECT,
360d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // larger on all sides
361d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10),
362d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // fully contained
363d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4),
364d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // outside top left
365d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, -1, -1),
366d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching top left corner
367d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, 0, 0),
368d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top left corner
369d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H / 4),
370d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top left and top right corners
371d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, DEV_H / 4),
372d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching entire top edge
373d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, 0),
374d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top right corner
375d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W  + 10, DEV_H / 4),
376d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // contained in x, overlapping top edge
377d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W / 4, -10, 3 * DEV_W  / 4, DEV_H / 4),
378d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // outside top right corner
379d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W + 1, -10, DEV_W + 10, -1),
380d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching top right corner
381d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W, -10, DEV_W + 10, 0),
382d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top left and bottom left corners
383d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H + 10),
384d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching entire left edge
385d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, 0, DEV_H + 10),
386d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping bottom left corner
387d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W / 4, DEV_H + 10),
388d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // contained in y, overlapping left edge
389d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H / 4, DEV_W / 4, 3 * DEV_H / 4),
390d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // outside bottom left corner
391d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H + 1, -1, DEV_H + 10),
392d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching bottom left corner
393d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H, 0, DEV_H + 10),
394d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping bottom left and bottom right corners
395d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
396d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching entire left edge
397d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(0, DEV_H, DEV_W, DEV_H + 10),
398d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping bottom right corner
399d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
400d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top right and bottom right corners
401d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H + 10),
402d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    };
403d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
404d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gCanvasConfigs); ++i) {
40567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        int glCtxTypeCnt = 1;
40667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#if SK_SUPPORT_GPU
4073cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        bool isGPUDevice = kGpu_TopLeft_DevType == gCanvasConfigs[i].fDevType ||
4083cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                           kGpu_BottomLeft_DevType == gCanvasConfigs[i].fDevType;
4093cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        if (isGPUDevice) {
41067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
41167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        }
41267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#endif
41367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
41467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            GrContext* context = NULL;
41567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#if SK_SUPPORT_GPU
4163cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            if (isGPUDevice) {
41767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                GrContextFactory::GLContextType type =
41867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    static_cast<GrContextFactory::GLContextType>(glCtxType);
41967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                if (!GrContextFactory::IsRenderingGLContext(type)) {
42067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    continue;
42167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                }
42267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                context = factory->get(type);
42367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                if (NULL == context) {
42467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    continue;
42567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                }
42667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            }
42767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#endif
42867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com
4291f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com            SkAutoTUnref<SkBaseDevice> device(createDevice(gCanvasConfigs[i], context));
43067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            SkCanvas canvas(device);
431d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
4327111d463cee893a479280c7af41757e709e33ef5reed@google.com            static const struct {
4337111d463cee893a479280c7af41757e709e33ef5reed@google.com                SkColorType fColorType;
4347111d463cee893a479280c7af41757e709e33ef5reed@google.com                SkAlphaType fAlphaType;
4357111d463cee893a479280c7af41757e709e33ef5reed@google.com            } gSrcConfigs[] = {
4367111d463cee893a479280c7af41757e709e33ef5reed@google.com                { kRGBA_8888_SkColorType, kPremul_SkAlphaType },
4377111d463cee893a479280c7af41757e709e33ef5reed@google.com                { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType },
4387111d463cee893a479280c7af41757e709e33ef5reed@google.com                { kBGRA_8888_SkColorType, kPremul_SkAlphaType },
4397111d463cee893a479280c7af41757e709e33ef5reed@google.com                { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType },
44067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            };
44167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            for (size_t r = 0; r < SK_ARRAY_COUNT(testRects); ++r) {
44267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                const SkIRect& rect = testRects[r];
44367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                for (int tightBmp = 0; tightBmp < 2; ++tightBmp) {
44467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    for (size_t c = 0; c < SK_ARRAY_COUNT(gSrcConfigs); ++c) {
4457111d463cee893a479280c7af41757e709e33ef5reed@google.com                        const SkColorType ct = gSrcConfigs[c].fColorType;
4467111d463cee893a479280c7af41757e709e33ef5reed@google.com                        const SkAlphaType at = gSrcConfigs[c].fAlphaType;
4477111d463cee893a479280c7af41757e709e33ef5reed@google.com
44867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        fillCanvas(&canvas);
44967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        SkBitmap bmp;
4507111d463cee893a479280c7af41757e709e33ef5reed@google.com                        REPORTER_ASSERT(reporter, setupBitmap(&bmp, ct, at, rect.width(),
4517111d463cee893a479280c7af41757e709e33ef5reed@google.com                                                              rect.height(), SkToBool(tightBmp)));
45267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        uint32_t idBefore = canvas.getDevice()->accessBitmap(false).getGenerationID();
4534cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
4547111d463cee893a479280c7af41757e709e33ef5reed@google.com                       // sk_tool_utils::write_pixels(&canvas, bmp, rect.fLeft, rect.fTop, ct, at);
4557111d463cee893a479280c7af41757e709e33ef5reed@google.com                        canvas.writePixels(bmp, rect.fLeft, rect.fTop);
4564cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
45767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        uint32_t idAfter = canvas.getDevice()->accessBitmap(false).getGenerationID();
4587111d463cee893a479280c7af41757e709e33ef5reed@google.com                        REPORTER_ASSERT(reporter, checkWrite(reporter, &canvas, bmp, rect.fLeft, rect.fTop));
459405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com
46067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        // we should change the genID iff pixels were actually written.
46167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        SkIRect canvasRect = SkIRect::MakeSize(canvas.getDeviceSize());
46267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        SkIRect writeRect = SkIRect::MakeXYWH(rect.fLeft, rect.fTop,
46367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                                                              bmp.width(), bmp.height());
46467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        bool intersects = SkIRect::Intersects(canvasRect, writeRect) ;
46567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                        REPORTER_ASSERT(reporter, intersects == (idBefore != idAfter));
46667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    }
467d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
468d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
469d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
470d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
471d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
472