blob: bc92bd81ffc9cb3870885c271eee92758307d64d [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
bsalomon@google.coma91e9232012-02-23 15:39:54 +00008#include "SkCanvas.h"
robertphillips7715e062016-04-22 10:57:16 -07009#include "SkSurface.h"
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +000010#include "Test.h"
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000011#include "sk_tool_utils.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000012
kkinnunen15302832015-12-01 04:35:26 -080013#include "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
reede5ea5002014-09-03 11:54:58 -070057 const SkImageInfo info = SkImageInfo::Make(bmp.width(), bmp.height(),
58 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);
Mike Reed4c790bd2018-02-08 14:10:40 -050077 sk_tool_utils::write_pixels(surf, readBmp1, 0, 0, gUnpremul[upmaIdx].fColorType,
kkinnunen15302832015-12-01 04:35:26 -080078 kUnpremul_SkAlphaType);
Mike Reedf1942192017-07-21 14:24:29 -040079 surf->readPixels(readBmp2, 0, 0);
kkinnunen15302832015-12-01 04:35:26 -080080
81 bool success = true;
82 for (int y = 0; y < 256 && success; ++y) {
83 const uint32_t* pixels1 = readBmp1.getAddr32(0, y);
84 const uint32_t* pixels2 = readBmp2.getAddr32(0, y);
85 for (int x = 0; x < 256 && success; ++x) {
86 // We see sporadic failures here. May help to see where it goes wrong.
87 if (pixels1[x] != pixels2[x]) {
88 SkDebugf("%x != %x, x = %d, y = %d\n", pixels1[x], pixels2[x], x, y);
bsalomon@google.com67b915d2013-02-04 16:13:32 +000089 }
kkinnunen15302832015-12-01 04:35:26 -080090 REPORTER_ASSERT(reporter, success = pixels1[x] == pixels2[x]);
bsalomon@google.coma91e9232012-02-23 15:39:54 +000091 }
92 }
93 }
94}
kkinnunen15302832015-12-01 04:35:26 -080095
96DEF_TEST(PremulAlphaRoundTrip, reporter) {
97 const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
robertphillips7715e062016-04-22 10:57:16 -070098
99 sk_sp<SkSurface> surf(SkSurface::MakeRaster(info));
100
101 test_premul_alpha_roundtrip(reporter, surf.get());
kkinnunen15302832015-12-01 04:35:26 -0800102}
bsalomon68d91342016-04-12 09:59:58 -0700103DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PremulAlphaRoundTrip_Gpu, reporter, ctxInfo) {
kkinnunen15302832015-12-01 04:35:26 -0800104 const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
robertphillips7715e062016-04-22 10:57:16 -0700105
bsalomon8b7451a2016-05-11 06:33:06 -0700106 sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(ctxInfo.grContext(),
robertphillips7715e062016-04-22 10:57:16 -0700107 SkBudgeted::kNo,
108 info));
109 test_premul_alpha_roundtrip(reporter, surf.get());
kkinnunen15302832015-12-01 04:35:26 -0800110}