blob: f4a252b157261bb3ab0a1741a984556f18047f81 [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"
10#include "tests/Test.h"
11#include "tools/ToolUtils.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000012
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/gpu/GrContext.h"
bsalomon@google.coma91e9232012-02-23 15:39:54 +000014
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000015static uint32_t pack_unpremul_rgba(SkColor c) {
16 uint32_t packed;
17 uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
18 byte[0] = SkColorGetR(c);
19 byte[1] = SkColorGetG(c);
20 byte[2] = SkColorGetB(c);
21 byte[3] = SkColorGetA(c);
22 return packed;
bsalomon@google.coma91e9232012-02-23 15:39:54 +000023}
24
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000025static uint32_t pack_unpremul_bgra(SkColor c) {
26 uint32_t packed;
27 uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
28 byte[0] = SkColorGetB(c);
29 byte[1] = SkColorGetG(c);
30 byte[2] = SkColorGetR(c);
31 byte[3] = SkColorGetA(c);
32 return packed;
33}
34
35typedef uint32_t (*PackUnpremulProc)(SkColor);
36
37const struct {
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +000038 SkColorType fColorType;
39 PackUnpremulProc fPackProc;
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000040} gUnpremul[] = {
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +000041 { kRGBA_8888_SkColorType, pack_unpremul_rgba },
42 { kBGRA_8888_SkColorType, pack_unpremul_bgra },
bsalomon@google.coma91e9232012-02-23 15:39:54 +000043};
44
Mike Reed4c790bd2018-02-08 14:10:40 -050045static void fill_surface(SkSurface* surf, SkColorType colorType, PackUnpremulProc proc) {
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000046 // Don't strictly need a bitmap, but its a handy way to allocate the pixels
47 SkBitmap bmp;
48 bmp.allocN32Pixels(256, 256);
49
50 for (int a = 0; a < 256; ++a) {
51 uint32_t* pixels = bmp.getAddr32(0, a);
52 for (int r = 0; r < 256; ++r) {
53 pixels[r] = proc(SkColorSetARGB(a, r, 0, 0));
54 }
55 }
56
Brian Salomon4bc0c1f2019-09-30 15:12:27 -040057 const SkImageInfo info = SkImageInfo::Make(bmp.dimensions(), colorType, kUnpremul_SkAlphaType);
Mike Reed4c790bd2018-02-08 14:10:40 -050058 surf->writePixels({info, bmp.getPixels(), bmp.rowBytes()}, 0, 0);
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000059}
60
robertphillips7715e062016-04-22 10:57:16 -070061static void test_premul_alpha_roundtrip(skiatest::Reporter* reporter, SkSurface* surf) {
kkinnunen15302832015-12-01 04:35:26 -080062 for (size_t upmaIdx = 0; upmaIdx < SK_ARRAY_COUNT(gUnpremul); ++upmaIdx) {
Mike Reed4c790bd2018-02-08 14:10:40 -050063 fill_surface(surf, gUnpremul[upmaIdx].fColorType, gUnpremul[upmaIdx].fPackProc);
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000064
kkinnunen15302832015-12-01 04:35:26 -080065 const SkImageInfo info = SkImageInfo::Make(256, 256, gUnpremul[upmaIdx].fColorType,
66 kUnpremul_SkAlphaType);
67 SkBitmap readBmp1;
68 readBmp1.allocPixels(info);
69 SkBitmap readBmp2;
70 readBmp2.allocPixels(info);
bsalomon@google.com67b915d2013-02-04 16:13:32 +000071
kkinnunen15302832015-12-01 04:35:26 -080072 readBmp1.eraseColor(0);
73 readBmp2.eraseColor(0);
74
Mike Reedf1942192017-07-21 14:24:29 -040075 surf->readPixels(readBmp1, 0, 0);
Brian Osmanb27667a2019-04-01 14:31:38 -040076 surf->writePixels(readBmp1, 0, 0);
Mike Reedf1942192017-07-21 14:24:29 -040077 surf->readPixels(readBmp2, 0, 0);
kkinnunen15302832015-12-01 04:35:26 -080078
79 bool success = true;
80 for (int y = 0; y < 256 && success; ++y) {
81 const uint32_t* pixels1 = readBmp1.getAddr32(0, y);
82 const uint32_t* pixels2 = readBmp2.getAddr32(0, y);
83 for (int x = 0; x < 256 && success; ++x) {
84 // We see sporadic failures here. May help to see where it goes wrong.
85 if (pixels1[x] != pixels2[x]) {
86 SkDebugf("%x != %x, x = %d, y = %d\n", pixels1[x], pixels2[x], x, y);
bsalomon@google.com67b915d2013-02-04 16:13:32 +000087 }
kkinnunen15302832015-12-01 04:35:26 -080088 REPORTER_ASSERT(reporter, success = pixels1[x] == pixels2[x]);
bsalomon@google.coma91e9232012-02-23 15:39:54 +000089 }
90 }
91 }
92}
kkinnunen15302832015-12-01 04:35:26 -080093
94DEF_TEST(PremulAlphaRoundTrip, reporter) {
95 const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
robertphillips7715e062016-04-22 10:57:16 -070096
97 sk_sp<SkSurface> surf(SkSurface::MakeRaster(info));
98
99 test_premul_alpha_roundtrip(reporter, surf.get());
kkinnunen15302832015-12-01 04:35:26 -0800100}
bsalomon68d91342016-04-12 09:59:58 -0700101DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PremulAlphaRoundTrip_Gpu, reporter, ctxInfo) {
kkinnunen15302832015-12-01 04:35:26 -0800102 const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
robertphillips7715e062016-04-22 10:57:16 -0700103
bsalomon8b7451a2016-05-11 06:33:06 -0700104 sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(ctxInfo.grContext(),
robertphillips7715e062016-04-22 10:57:16 -0700105 SkBudgeted::kNo,
106 info));
107 test_premul_alpha_roundtrip(reporter, surf.get());
kkinnunen15302832015-12-01 04:35:26 -0800108}