blob: c9a7073d1bbab786df746b32eaabec17ea434b76 [file] [log] [blame]
bsalomon@google.coma91e9232012-02-23 15:39:54 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkCanvas.h"
9#include "include/core/SkSurface.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040010#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "tests/Test.h"
12#include "tools/ToolUtils.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000013
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/gpu/GrContext.h"
bsalomon@google.coma91e9232012-02-23 15:39:54 +000015
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000016static uint32_t pack_unpremul_rgba(SkColor c) {
17 uint32_t packed;
18 uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
19 byte[0] = SkColorGetR(c);
20 byte[1] = SkColorGetG(c);
21 byte[2] = SkColorGetB(c);
22 byte[3] = SkColorGetA(c);
23 return packed;
bsalomon@google.coma91e9232012-02-23 15:39:54 +000024}
25
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000026static uint32_t pack_unpremul_bgra(SkColor c) {
27 uint32_t packed;
28 uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
29 byte[0] = SkColorGetB(c);
30 byte[1] = SkColorGetG(c);
31 byte[2] = SkColorGetR(c);
32 byte[3] = SkColorGetA(c);
33 return packed;
34}
35
36typedef uint32_t (*PackUnpremulProc)(SkColor);
37
38const struct {
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +000039 SkColorType fColorType;
40 PackUnpremulProc fPackProc;
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000041} gUnpremul[] = {
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +000042 { kRGBA_8888_SkColorType, pack_unpremul_rgba },
43 { kBGRA_8888_SkColorType, pack_unpremul_bgra },
bsalomon@google.coma91e9232012-02-23 15:39:54 +000044};
45
Mike Reed4c790bd2018-02-08 14:10:40 -050046static void fill_surface(SkSurface* surf, SkColorType colorType, PackUnpremulProc proc) {
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000047 // Don't strictly need a bitmap, but its a handy way to allocate the pixels
48 SkBitmap bmp;
49 bmp.allocN32Pixels(256, 256);
50
51 for (int a = 0; a < 256; ++a) {
52 uint32_t* pixels = bmp.getAddr32(0, a);
53 for (int r = 0; r < 256; ++r) {
54 pixels[r] = proc(SkColorSetARGB(a, r, 0, 0));
55 }
56 }
57
Brian Salomon4bc0c1f2019-09-30 15:12:27 -040058 const SkImageInfo info = SkImageInfo::Make(bmp.dimensions(), colorType, kUnpremul_SkAlphaType);
Mike Reed4c790bd2018-02-08 14:10:40 -050059 surf->writePixels({info, bmp.getPixels(), bmp.rowBytes()}, 0, 0);
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000060}
61
robertphillips7715e062016-04-22 10:57:16 -070062static void test_premul_alpha_roundtrip(skiatest::Reporter* reporter, SkSurface* surf) {
kkinnunen15302832015-12-01 04:35:26 -080063 for (size_t upmaIdx = 0; upmaIdx < SK_ARRAY_COUNT(gUnpremul); ++upmaIdx) {
Mike Reed4c790bd2018-02-08 14:10:40 -050064 fill_surface(surf, gUnpremul[upmaIdx].fColorType, gUnpremul[upmaIdx].fPackProc);
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000065
kkinnunen15302832015-12-01 04:35:26 -080066 const SkImageInfo info = SkImageInfo::Make(256, 256, gUnpremul[upmaIdx].fColorType,
67 kUnpremul_SkAlphaType);
68 SkBitmap readBmp1;
69 readBmp1.allocPixels(info);
70 SkBitmap readBmp2;
71 readBmp2.allocPixels(info);
bsalomon@google.com67b915d2013-02-04 16:13:32 +000072
kkinnunen15302832015-12-01 04:35:26 -080073 readBmp1.eraseColor(0);
74 readBmp2.eraseColor(0);
75
Mike Reedf1942192017-07-21 14:24:29 -040076 surf->readPixels(readBmp1, 0, 0);
Brian Osmanb27667a2019-04-01 14:31:38 -040077 surf->writePixels(readBmp1, 0, 0);
Mike Reedf1942192017-07-21 14:24:29 -040078 surf->readPixels(readBmp2, 0, 0);
kkinnunen15302832015-12-01 04:35:26 -080079
80 bool success = true;
81 for (int y = 0; y < 256 && success; ++y) {
82 const uint32_t* pixels1 = readBmp1.getAddr32(0, y);
83 const uint32_t* pixels2 = readBmp2.getAddr32(0, y);
84 for (int x = 0; x < 256 && success; ++x) {
85 // We see sporadic failures here. May help to see where it goes wrong.
86 if (pixels1[x] != pixels2[x]) {
87 SkDebugf("%x != %x, x = %d, y = %d\n", pixels1[x], pixels2[x], x, y);
bsalomon@google.com67b915d2013-02-04 16:13:32 +000088 }
kkinnunen15302832015-12-01 04:35:26 -080089 REPORTER_ASSERT(reporter, success = pixels1[x] == pixels2[x]);
bsalomon@google.coma91e9232012-02-23 15:39:54 +000090 }
91 }
92 }
93}
kkinnunen15302832015-12-01 04:35:26 -080094
95DEF_TEST(PremulAlphaRoundTrip, reporter) {
96 const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
robertphillips7715e062016-04-22 10:57:16 -070097
98 sk_sp<SkSurface> surf(SkSurface::MakeRaster(info));
99
100 test_premul_alpha_roundtrip(reporter, surf.get());
kkinnunen15302832015-12-01 04:35:26 -0800101}
bsalomon68d91342016-04-12 09:59:58 -0700102DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PremulAlphaRoundTrip_Gpu, reporter, ctxInfo) {
kkinnunen15302832015-12-01 04:35:26 -0800103 const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
robertphillips7715e062016-04-22 10:57:16 -0700104
Robert Phillips6d344c32020-07-06 10:56:46 -0400105 sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(ctxInfo.directContext(),
106 SkBudgeted::kNo, info));
robertphillips7715e062016-04-22 10:57:16 -0700107 test_premul_alpha_roundtrip(reporter, surf.get());
kkinnunen15302832015-12-01 04:35:26 -0800108}