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
8d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com#include "SkCanvas.h"
9cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#include "SkColorPriv.h"
104b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h"
11d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com#include "SkRegion.h"
124af35f348b2e2f6c428819118eb7a2f2fff53a74reed#include "SkSurface.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
171530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#include "GrContext.h"
18cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
19d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
201530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#include <initializer_list>
211530283c483cb88aa725bce50a6d193dd00ee570kkinnunen
22d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comstatic const int DEV_W = 100, DEV_H = 100;
23d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comstatic const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);
24d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comstatic const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1,
25d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                                                DEV_H * SK_Scalar1);
26d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comstatic const U8CPU DEV_PAD = 0xee;
27d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
28f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomonstatic SkPMColor get_canvas_color(int x, int y) {
29d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkASSERT(x >= 0 && x < DEV_W);
30d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkASSERT(y >= 0 && y < DEV_H);
31d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
32d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU r = x;
33d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU g = y;
34d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU b = 0xc;
35d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
3631648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com    U8CPU a = 0x0;
37d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    switch ((x+y) % 5) {
38d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 0:
39d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0xff;
40d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
41d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 1:
42d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x80;
43d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
44d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 2:
45d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0xCC;
46d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
47d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 3:
48d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x00;
49d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
5031648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com        case 4:
5131648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com            a = 0x01;
5231648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com            break;
53d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
54d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return SkPremultiplyARGBInline(a, r, g, b);
55d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
56d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
57d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com// assumes any premu/.unpremul has been applied
58f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomonstatic uint32_t pack_color_type(SkColorType ct, U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
59d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    uint32_t r32;
60d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    uint8_t* result = reinterpret_cast<uint8_t*>(&r32);
617111d463cee893a479280c7af41757e709e33ef5reed@google.com    switch (ct) {
627111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kBGRA_8888_SkColorType:
63d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[0] = b;
64d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[1] = g;
65d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[2] = r;
66d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[3] = a;
67d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
687111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kRGBA_8888_SkColorType:
69d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[0] = r;
70d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[1] = g;
71d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[2] = b;
72d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            result[3] = a;
73d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
74d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        default:
75d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            SkASSERT(0);
76d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            return 0;
77d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
78d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return r32;
79d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
80d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
81f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomonstatic uint32_t get_bitmap_color(int x, int y, int w, SkColorType ct, SkAlphaType at) {
82d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int n = y * w + x;
83d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU b = n & 0xff;
84d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU g = (n >> 8) & 0xff;
85d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    U8CPU r = (n >> 16) & 0xff;
8631648eb1cfe19257ec077efebb11ab251bfd25f7bsalomon@google.com    U8CPU a = 0;
87d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    switch ((x+y) % 5) {
88d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 4:
89d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0xff;
90d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
91d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 3:
92d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x80;
93d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
94d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 2:
95d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0xCC;
96d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
97d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 1:
98d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x01;
99d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
100d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        case 0:
101d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            a = 0x00;
102d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            break;
103d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
1047111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (kPremul_SkAlphaType == at) {
105d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        r = SkMulDiv255Ceiling(r, a);
106d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        g = SkMulDiv255Ceiling(g, a);
107d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        b = SkMulDiv255Ceiling(b, a);
108d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
109f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon    return pack_color_type(ct, a, r, g , b);
110d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
111d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
112f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomonstatic void fill_canvas(SkCanvas* canvas) {
1134cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBitmap bmp;
114d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    if (bmp.isNull()) {
115848250415eddc54075f7eb8795e8db79e749c6abreed        bmp.allocN32Pixels(DEV_W, DEV_H);
116d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        for (int y = 0; y < DEV_H; ++y) {
117d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            for (int x = 0; x < DEV_W; ++x) {
118f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon                *bmp.getAddr32(x, y) = get_canvas_color(x, y);
119d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
120d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
121d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
122d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->save();
123d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->setMatrix(SkMatrix::I());
124d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->clipRect(DEV_RECT_S, SkRegion::kReplace_Op);
125d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkPaint paint;
126d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
127d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->drawBitmap(bmp, 0, 0, &paint);
128d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    canvas->restore();
129d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
130d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
1317111d463cee893a479280c7af41757e709e33ef5reed@google.com/**
1327111d463cee893a479280c7af41757e709e33ef5reed@google.com *  Lucky for us, alpha is always in the same spot (SK_A32_SHIFT), for both RGBA and BGRA.
1337111d463cee893a479280c7af41757e709e33ef5reed@google.com *  Thus this routine doesn't need to know the exact colortype
1347111d463cee893a479280c7af41757e709e33ef5reed@google.com */
1357111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic uint32_t premul(uint32_t color) {
1367111d463cee893a479280c7af41757e709e33ef5reed@google.com    unsigned a = SkGetPackedA32(color);
1377111d463cee893a479280c7af41757e709e33ef5reed@google.com    // these next three are not necessarily r,g,b in that order, but they are r,g,b in some order.
1387111d463cee893a479280c7af41757e709e33ef5reed@google.com    unsigned c0 = SkGetPackedR32(color);
1397111d463cee893a479280c7af41757e709e33ef5reed@google.com    unsigned c1 = SkGetPackedG32(color);
1407111d463cee893a479280c7af41757e709e33ef5reed@google.com    unsigned c2 = SkGetPackedB32(color);
1417111d463cee893a479280c7af41757e709e33ef5reed@google.com    c0 = SkMulDiv255Ceiling(c0, a);
1427111d463cee893a479280c7af41757e709e33ef5reed@google.com    c1 = SkMulDiv255Ceiling(c1, a);
1437111d463cee893a479280c7af41757e709e33ef5reed@google.com    c2 = SkMulDiv255Ceiling(c2, a);
1447111d463cee893a479280c7af41757e709e33ef5reed@google.com    return SkPackARGB32NoCheck(a, c0, c1, c2);
1457111d463cee893a479280c7af41757e709e33ef5reed@google.com}
1467111d463cee893a479280c7af41757e709e33ef5reed@google.com
1477111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic SkPMColor convert_to_PMColor(SkColorType ct, SkAlphaType at, uint32_t color) {
1487111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (kUnpremul_SkAlphaType == at) {
1497111d463cee893a479280c7af41757e709e33ef5reed@google.com        color = premul(color);
1507111d463cee893a479280c7af41757e709e33ef5reed@google.com    }
1517111d463cee893a479280c7af41757e709e33ef5reed@google.com    switch (ct) {
1527111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kRGBA_8888_SkColorType:
1537111d463cee893a479280c7af41757e709e33ef5reed@google.com            color = SkSwizzle_RGBA_to_PMColor(color);
154e14792d99fc7a1a314ef5e2ca5b269239468355acommit-bot@chromium.org            break;
1557111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kBGRA_8888_SkColorType:
1567111d463cee893a479280c7af41757e709e33ef5reed@google.com            color = SkSwizzle_BGRA_to_PMColor(color);
1571121170477302e25ef2a020cf2092aa6b399b3efreed@google.com            break;
158231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org        default:
1597111d463cee893a479280c7af41757e709e33ef5reed@google.com            SkASSERT(0);
1607111d463cee893a479280c7af41757e709e33ef5reed@google.com            break;
161231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org    }
1627111d463cee893a479280c7af41757e709e33ef5reed@google.com    return color;
163d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
164d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
165f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomonstatic bool check_pixel(SkPMColor a, SkPMColor b, bool didPremulConversion) {
166d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    if (!didPremulConversion) {
167d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return a == b;
168d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
169d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aA = static_cast<int32_t>(SkGetPackedA32(a));
170d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aR = static_cast<int32_t>(SkGetPackedR32(a));
171d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aG = static_cast<int32_t>(SkGetPackedG32(a));
172d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t aB = SkGetPackedB32(a);
173d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
174d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bA = static_cast<int32_t>(SkGetPackedA32(b));
175d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bR = static_cast<int32_t>(SkGetPackedR32(b));
176d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bG = static_cast<int32_t>(SkGetPackedG32(b));
177d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    int32_t bB = static_cast<int32_t>(SkGetPackedB32(b));
178d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
179d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return aA == bA &&
180d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com           SkAbs32(aR - bR) <= 1 &&
181d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com           SkAbs32(aG - bG) <= 1 &&
182d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com           SkAbs32(aB - bB) <= 1;
183d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
184d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
18552d9ac6c92ddf33b3b05eb77ba9509a7aa441657reedstatic bool check_write(skiatest::Reporter* reporter, SkCanvas* canvas, const SkBitmap& bitmap,
1867111d463cee893a479280c7af41757e709e33ef5reed@google.com                       int writeX, int writeY) {
18752d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed    const SkImageInfo canvasInfo = canvas->imageInfo();
1887111d463cee893a479280c7af41757e709e33ef5reed@google.com    size_t canvasRowBytes;
1897111d463cee893a479280c7af41757e709e33ef5reed@google.com    const uint32_t* canvasPixels;
1907111d463cee893a479280c7af41757e709e33ef5reed@google.com
1917111d463cee893a479280c7af41757e709e33ef5reed@google.com    // Can't use canvas->peekPixels(), as we are trying to look at GPU pixels sometimes as well.
1927111d463cee893a479280c7af41757e709e33ef5reed@google.com    // At some point this will be unsupported, as we won't allow accessBitmap() to magically call
1937111d463cee893a479280c7af41757e709e33ef5reed@google.com    // readPixels for the client.
1947111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkBitmap secretDevBitmap;
195f622a6c8fd176acf9944de8df00d7f0bb56b67d3halcanary    canvas->readPixels(canvasInfo.bounds(), &secretDevBitmap);
19652d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed
1977111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkAutoLockPixels alp(secretDevBitmap);
1987111d463cee893a479280c7af41757e709e33ef5reed@google.com    canvasRowBytes = secretDevBitmap.rowBytes();
1997111d463cee893a479280c7af41757e709e33ef5reed@google.com    canvasPixels = static_cast<const uint32_t*>(secretDevBitmap.getPixels());
2007111d463cee893a479280c7af41757e709e33ef5reed@google.com
20196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == canvasPixels) {
202d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return false;
203d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
2047111d463cee893a479280c7af41757e709e33ef5reed@google.com
2057111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (canvasInfo.width() != DEV_W ||
2067111d463cee893a479280c7af41757e709e33ef5reed@google.com        canvasInfo.height() != DEV_H ||
20728fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        canvasInfo.colorType() != kN32_SkColorType) {
208d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return false;
209d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
210d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
2117111d463cee893a479280c7af41757e709e33ef5reed@google.com    const SkImageInfo bmInfo = bitmap.info();
2127111d463cee893a479280c7af41757e709e33ef5reed@google.com
213d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    SkIRect writeRect = SkIRect::MakeXYWH(writeX, writeY, bitmap.width(), bitmap.height());
214d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    for (int cy = 0; cy < DEV_H; ++cy) {
215d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        for (int cx = 0; cx < DEV_W; ++cx) {
2167111d463cee893a479280c7af41757e709e33ef5reed@google.com            SkPMColor canvasPixel = canvasPixels[cx];
217d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            if (writeRect.contains(cx, cy)) {
218d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                int bx = cx - writeX;
219d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                int by = cy - writeY;
220f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon                uint32_t bmpColor8888 = get_bitmap_color(bx, by, bitmap.width(),
2217111d463cee893a479280c7af41757e709e33ef5reed@google.com                                                       bmInfo.colorType(), bmInfo.alphaType());
2227111d463cee893a479280c7af41757e709e33ef5reed@google.com                bool mul = (kUnpremul_SkAlphaType == bmInfo.alphaType());
2237111d463cee893a479280c7af41757e709e33ef5reed@google.com                SkPMColor bmpPMColor = convert_to_PMColor(bmInfo.colorType(), bmInfo.alphaType(),
2247111d463cee893a479280c7af41757e709e33ef5reed@google.com                                                          bmpColor8888);
225f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon                if (!check_pixel(bmpPMColor, canvasPixel, mul)) {
226f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon                    ERRORF(reporter, "Expected canvas pixel at %d, %d to be 0x%08x, got 0x%08x. "
227f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon                           "Write performed premul: %d", cx, cy, bmpPMColor, canvasPixel, mul);
22872f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                    return false;
229d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
230d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            } else {
231f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon                SkPMColor testColor = get_canvas_color(cx, cy);
232f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon                if (canvasPixel != testColor) {
233f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon                    ERRORF(reporter, "Canvas pixel outside write rect at %d, %d changed."
234f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon                           " Should be 0x%08x, got 0x%08x. ", cx, cy, testColor, canvasPixel);
23572f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                    return false;
236d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
237d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
238d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
239d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        if (cy != DEV_H -1) {
2407111d463cee893a479280c7af41757e709e33ef5reed@google.com            const char* pad = reinterpret_cast<const char*>(canvasPixels + DEV_W);
241d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            for (size_t px = 0; px < canvasRowBytes - 4 * DEV_W; ++px) {
242d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                bool check;
243d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                REPORTER_ASSERT(reporter, check = (pad[px] == static_cast<char>(DEV_PAD)));
244d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                if (!check) {
24572f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com                    return false;
246d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                }
247d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
248d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
2497111d463cee893a479280c7af41757e709e33ef5reed@google.com        canvasPixels += canvasRowBytes/4;
250d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
251d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
25272f3dca451f4739e20be0b4b198813677339205cbsalomon@google.com    return true;
253d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
254d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
255fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org#include "SkMallocPixelRef.h"
256fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org
257fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org// This is a tricky pattern, because we have to setConfig+rowBytes AND specify
258fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org// a custom pixelRef (which also has to specify its rowBytes), so we have to be
259fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org// sure that the two rowBytes match (and the infos match).
260fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org//
261f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomonstatic bool alloc_row_bytes(SkBitmap* bm, const SkImageInfo& info, size_t rowBytes) {
262a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    if (!bm->setInfo(info, rowBytes)) {
263fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org        return false;
264fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    }
26596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, rowBytes, nullptr);
266fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    bm->setPixelRef(pr)->unref();
267fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    return true;
268fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org}
269fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org
27052d9ac6c92ddf33b3b05eb77ba9509a7aa441657reedstatic void free_pixels(void* pixels, void* ctx) {
27152d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed    sk_free(pixels);
27252d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed}
27352d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed
27452d9ac6c92ddf33b3b05eb77ba9509a7aa441657reedstatic bool setup_bitmap(SkBitmap* bm, SkColorType ct, SkAlphaType at, int w, int h, int tightRB) {
2757111d463cee893a479280c7af41757e709e33ef5reed@google.com    size_t rowBytes = tightRB ? 0 : 4 * w + 60;
2767111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkImageInfo info = SkImageInfo::Make(w, h, ct, at);
277f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon    if (!alloc_row_bytes(bm, info, rowBytes)) {
278d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        return false;
279d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
2807111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkAutoLockPixels alp(*bm);
281d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    for (int y = 0; y < h; ++y) {
282d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        for (int x = 0; x < w; ++x) {
283f0674516cb18f6b13e34f404ff5793d9b9ebb56cbsalomon            *bm->getAddr32(x, y) = get_bitmap_color(x, y, w, ct, at);
284d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
285d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
286d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    return true;
287d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
288d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
2894af35f348b2e2f6c428819118eb7a2f2fff53a74reedstatic void call_writepixels(SkCanvas* canvas) {
2904af35f348b2e2f6c428819118eb7a2f2fff53a74reed    const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
2914af35f348b2e2f6c428819118eb7a2f2fff53a74reed    SkPMColor pixel = 0;
2924af35f348b2e2f6c428819118eb7a2f2fff53a74reed    canvas->writePixels(info, &pixel, sizeof(SkPMColor), 0, 0);
2934af35f348b2e2f6c428819118eb7a2f2fff53a74reed}
2944af35f348b2e2f6c428819118eb7a2f2fff53a74reed
2951530283c483cb88aa725bce50a6d193dd00ee570kkinnunenDEF_TEST(WritePixelsSurfaceGenID, reporter) {
2964af35f348b2e2f6c428819118eb7a2f2fff53a74reed    const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
2974af35f348b2e2f6c428819118eb7a2f2fff53a74reed    SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
2984af35f348b2e2f6c428819118eb7a2f2fff53a74reed    uint32_t genID1 = surface->generationID();
2994af35f348b2e2f6c428819118eb7a2f2fff53a74reed    call_writepixels(surface->getCanvas());
3004af35f348b2e2f6c428819118eb7a2f2fff53a74reed    uint32_t genID2 = surface->generationID();
3014af35f348b2e2f6c428819118eb7a2f2fff53a74reed    REPORTER_ASSERT(reporter, genID1 != genID2);
3024af35f348b2e2f6c428819118eb7a2f2fff53a74reed}
3034af35f348b2e2f6c428819118eb7a2f2fff53a74reed
3041530283c483cb88aa725bce50a6d193dd00ee570kkinnunenstatic void test_write_pixels(skiatest::Reporter* reporter, SkSurface* surface) {
305d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    const SkIRect testRects[] = {
306d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // entire thing
307d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        DEV_RECT,
308d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // larger on all sides
309d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10),
310d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // fully contained
311d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4),
312d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // outside top left
313d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, -1, -1),
314d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching top left corner
315d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, 0, 0),
316d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top left corner
317d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H / 4),
318d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top left and top right corners
319d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, DEV_H / 4),
320d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching entire top edge
321d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, 0),
322d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top right corner
323d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W  + 10, DEV_H / 4),
324d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // contained in x, overlapping top edge
325d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W / 4, -10, 3 * DEV_W  / 4, DEV_H / 4),
326d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // outside top right corner
327d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W + 1, -10, DEV_W + 10, -1),
328d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching top right corner
329d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(DEV_W, -10, DEV_W + 10, 0),
330d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top left and bottom left corners
331d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H + 10),
332d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching entire left edge
333d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, -10, 0, DEV_H + 10),
334d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping bottom left corner
335d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W / 4, DEV_H + 10),
336d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // contained in y, overlapping left edge
337d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H / 4, DEV_W / 4, 3 * DEV_H / 4),
338d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // outside bottom left corner
339d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H + 1, -1, DEV_H + 10),
340d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching bottom left corner
341d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, DEV_H, 0, DEV_H + 10),
342d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping bottom left and bottom right corners
343d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
344d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // touching entire left edge
345d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(0, DEV_H, DEV_W, DEV_H + 10),
346d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping bottom right corner
347d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
348d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        // overlapping top right and bottom right corners
349d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H + 10),
350d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    };
351d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com
3521530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    SkCanvas& canvas = *surface->getCanvas();
35367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com
3541530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    static const struct {
3551530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        SkColorType fColorType;
3561530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        SkAlphaType fAlphaType;
3571530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    } gSrcConfigs[] = {
3581530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        { kRGBA_8888_SkColorType, kPremul_SkAlphaType },
3591530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType },
3601530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        { kBGRA_8888_SkColorType, kPremul_SkAlphaType },
3611530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType },
3621530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    };
3631530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    for (size_t r = 0; r < SK_ARRAY_COUNT(testRects); ++r) {
3641530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        const SkIRect& rect = testRects[r];
3651530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        for (int tightBmp = 0; tightBmp < 2; ++tightBmp) {
3661530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            for (size_t c = 0; c < SK_ARRAY_COUNT(gSrcConfigs); ++c) {
3671530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                const SkColorType ct = gSrcConfigs[c].fColorType;
3681530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                const SkAlphaType at = gSrcConfigs[c].fAlphaType;
3691530283c483cb88aa725bce50a6d193dd00ee570kkinnunen
3701530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                fill_canvas(&canvas);
3711530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                SkBitmap bmp;
3721530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                REPORTER_ASSERT(reporter, setup_bitmap(&bmp, ct, at, rect.width(),
3731530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                                       rect.height(), SkToBool(tightBmp)));
3741530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                uint32_t idBefore = surface->generationID();
3751530283c483cb88aa725bce50a6d193dd00ee570kkinnunen
3761530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                // sk_tool_utils::write_pixels(&canvas, bmp, rect.fLeft, rect.fTop, ct, at);
3771530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                canvas.writePixels(bmp, rect.fLeft, rect.fTop);
3781530283c483cb88aa725bce50a6d193dd00ee570kkinnunen
3791530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                uint32_t idAfter = surface->generationID();
3801530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                REPORTER_ASSERT(reporter, check_write(reporter, &canvas, bmp,
3811530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                                      rect.fLeft, rect.fTop));
3821530283c483cb88aa725bce50a6d193dd00ee570kkinnunen
3831530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                // we should change the genID iff pixels were actually written.
3841530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                SkIRect canvasRect = SkIRect::MakeSize(canvas.getDeviceSize());
3851530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                SkIRect writeRect = SkIRect::MakeXYWH(rect.fLeft, rect.fTop,
3861530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                                      bmp.width(), bmp.height());
3871530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                bool intersects = SkIRect::Intersects(canvasRect, writeRect) ;
3881530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                REPORTER_ASSERT(reporter, intersects == (idBefore != idAfter));
389d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com            }
390d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com        }
391d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com    }
392d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com}
3931530283c483cb88aa725bce50a6d193dd00ee570kkinnunenDEF_TEST(WritePixels, reporter) {
3941530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    const SkImageInfo info = SkImageInfo::MakeN32Premul(DEV_W, DEV_H);
3951530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    for (auto& tightRowBytes : { true, false }) {
3961530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        const size_t rowBytes = tightRowBytes ? info.minRowBytes() : 4 * DEV_W + 100;
3971530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        const size_t size = info.getSafeSize(rowBytes);
3981530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        void* pixels = sk_malloc_throw(size);
3991530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        // if rowBytes isn't tight then set the padding to a known value
4001530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        if (!tightRowBytes) {
4011530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            memset(pixels, DEV_PAD, size);
4021530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        }
4031530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterDirectReleaseProc(info, pixels, rowBytes, free_pixels, nullptr));
4041530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        test_write_pixels(reporter, surface);
4051530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    }
4061530283c483cb88aa725bce50a6d193dd00ee570kkinnunen}
4071530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#if SK_SUPPORT_GPU
4081530283c483cb88aa725bce50a6d193dd00ee570kkinnunenDEF_GPUTEST_FOR_RENDERING_CONTEXTS(WritePixels_Gpu, reporter, context) {
4091530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    for (auto& origin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin }) {
4101530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        GrSurfaceDesc desc;
4111530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        desc.fFlags = kRenderTarget_GrSurfaceFlag;
4121530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        desc.fWidth = DEV_W;
4131530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        desc.fHeight = DEV_H;
4141530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        desc.fConfig = kSkia8888_GrPixelConfig;
4151530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        desc.fOrigin = origin;
4165ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc,
4175ec26ae9bfca635ccc98283aad5deda11519d826bsalomon                                                                                  SkBudgeted::kNo));
4181530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(texture->asRenderTarget()));
4191530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        test_write_pixels(reporter, surface);
4201530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    }
4211530283c483cb88aa725bce50a6d193dd00ee570kkinnunen}
4221530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#endif
423