blob: 9227b33691cd5bf278e4059c58219df6a537a948 [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
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000014static uint32_t pack_unpremul_rgba(SkColor c) {
15 uint32_t packed;
16 uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
17 byte[0] = SkColorGetR(c);
18 byte[1] = SkColorGetG(c);
19 byte[2] = SkColorGetB(c);
20 byte[3] = SkColorGetA(c);
21 return packed;
bsalomon@google.coma91e9232012-02-23 15:39:54 +000022}
23
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000024static uint32_t pack_unpremul_bgra(SkColor c) {
25 uint32_t packed;
26 uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
27 byte[0] = SkColorGetB(c);
28 byte[1] = SkColorGetG(c);
29 byte[2] = SkColorGetR(c);
30 byte[3] = SkColorGetA(c);
31 return packed;
32}
33
34typedef uint32_t (*PackUnpremulProc)(SkColor);
35
36const struct {
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +000037 SkColorType fColorType;
38 PackUnpremulProc fPackProc;
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000039} gUnpremul[] = {
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +000040 { kRGBA_8888_SkColorType, pack_unpremul_rgba },
41 { kBGRA_8888_SkColorType, pack_unpremul_bgra },
bsalomon@google.coma91e9232012-02-23 15:39:54 +000042};
43
Mike Reed4c790bd2018-02-08 14:10:40 -050044static void fill_surface(SkSurface* surf, SkColorType colorType, PackUnpremulProc proc) {
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000045 // Don't strictly need a bitmap, but its a handy way to allocate the pixels
46 SkBitmap bmp;
47 bmp.allocN32Pixels(256, 256);
48
49 for (int a = 0; a < 256; ++a) {
50 uint32_t* pixels = bmp.getAddr32(0, a);
51 for (int r = 0; r < 256; ++r) {
52 pixels[r] = proc(SkColorSetARGB(a, r, 0, 0));
53 }
54 }
55
Brian Salomon4bc0c1f2019-09-30 15:12:27 -040056 const SkImageInfo info = SkImageInfo::Make(bmp.dimensions(), colorType, kUnpremul_SkAlphaType);
Mike Reed4c790bd2018-02-08 14:10:40 -050057 surf->writePixels({info, bmp.getPixels(), bmp.rowBytes()}, 0, 0);
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000058}
59
robertphillips7715e062016-04-22 10:57:16 -070060static void test_premul_alpha_roundtrip(skiatest::Reporter* reporter, SkSurface* surf) {
kkinnunen15302832015-12-01 04:35:26 -080061 for (size_t upmaIdx = 0; upmaIdx < SK_ARRAY_COUNT(gUnpremul); ++upmaIdx) {
Mike Reed4c790bd2018-02-08 14:10:40 -050062 fill_surface(surf, gUnpremul[upmaIdx].fColorType, gUnpremul[upmaIdx].fPackProc);
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000063
kkinnunen15302832015-12-01 04:35:26 -080064 const SkImageInfo info = SkImageInfo::Make(256, 256, gUnpremul[upmaIdx].fColorType,
65 kUnpremul_SkAlphaType);
66 SkBitmap readBmp1;
67 readBmp1.allocPixels(info);
68 SkBitmap readBmp2;
69 readBmp2.allocPixels(info);
bsalomon@google.com67b915d2013-02-04 16:13:32 +000070
kkinnunen15302832015-12-01 04:35:26 -080071 readBmp1.eraseColor(0);
72 readBmp2.eraseColor(0);
73
Mike Reedf1942192017-07-21 14:24:29 -040074 surf->readPixels(readBmp1, 0, 0);
Brian Osmanb27667a2019-04-01 14:31:38 -040075 surf->writePixels(readBmp1, 0, 0);
Mike Reedf1942192017-07-21 14:24:29 -040076 surf->readPixels(readBmp2, 0, 0);
kkinnunen15302832015-12-01 04:35:26 -080077
78 bool success = true;
79 for (int y = 0; y < 256 && success; ++y) {
80 const uint32_t* pixels1 = readBmp1.getAddr32(0, y);
81 const uint32_t* pixels2 = readBmp2.getAddr32(0, y);
82 for (int x = 0; x < 256 && success; ++x) {
83 // We see sporadic failures here. May help to see where it goes wrong.
84 if (pixels1[x] != pixels2[x]) {
85 SkDebugf("%x != %x, x = %d, y = %d\n", pixels1[x], pixels2[x], x, y);
bsalomon@google.com67b915d2013-02-04 16:13:32 +000086 }
kkinnunen15302832015-12-01 04:35:26 -080087 REPORTER_ASSERT(reporter, success = pixels1[x] == pixels2[x]);
bsalomon@google.coma91e9232012-02-23 15:39:54 +000088 }
89 }
90 }
91}
kkinnunen15302832015-12-01 04:35:26 -080092
93DEF_TEST(PremulAlphaRoundTrip, reporter) {
94 const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
robertphillips7715e062016-04-22 10:57:16 -070095
96 sk_sp<SkSurface> surf(SkSurface::MakeRaster(info));
97
98 test_premul_alpha_roundtrip(reporter, surf.get());
kkinnunen15302832015-12-01 04:35:26 -080099}
bsalomon68d91342016-04-12 09:59:58 -0700100DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PremulAlphaRoundTrip_Gpu, reporter, ctxInfo) {
kkinnunen15302832015-12-01 04:35:26 -0800101 const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
robertphillips7715e062016-04-22 10:57:16 -0700102
Robert Phillips6d344c32020-07-06 10:56:46 -0400103 sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(ctxInfo.directContext(),
104 SkBudgeted::kNo, info));
robertphillips7715e062016-04-22 10:57:16 -0700105 test_premul_alpha_roundtrip(reporter, surf.get());
kkinnunen15302832015-12-01 04:35:26 -0800106}