1a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com/* 2a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * Copyright 2011 Google Inc. 3a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * 4a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 5a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * found in the LICENSE file. 6a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com */ 7a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com 8a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkCanvas.h" 97715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips#include "SkSurface.h" 104ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "Test.h" 114cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org#include "sk_tool_utils.h" 12cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 13cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU 141530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#include "GrContext.h" 15cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 16a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com 174cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgstatic uint32_t pack_unpremul_rgba(SkColor c) { 184cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org uint32_t packed; 194cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org uint8_t* byte = reinterpret_cast<uint8_t*>(&packed); 204cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org byte[0] = SkColorGetR(c); 214cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org byte[1] = SkColorGetG(c); 224cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org byte[2] = SkColorGetB(c); 234cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org byte[3] = SkColorGetA(c); 244cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org return packed; 254cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org} 264cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org 274cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgstatic uint32_t pack_unpremul_bgra(SkColor c) { 284cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org uint32_t packed; 294cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org uint8_t* byte = reinterpret_cast<uint8_t*>(&packed); 304cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org byte[0] = SkColorGetB(c); 314cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org byte[1] = SkColorGetG(c); 324cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org byte[2] = SkColorGetR(c); 334cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org byte[3] = SkColorGetA(c); 344cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org return packed; 354cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org} 364cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org 374cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgtypedef uint32_t (*PackUnpremulProc)(SkColor); 384cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org 394cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgconst struct { 40a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org SkColorType fColorType; 41a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org PackUnpremulProc fPackProc; 424cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org} gUnpremul[] = { 43a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org { kRGBA_8888_SkColorType, pack_unpremul_rgba }, 44a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org { kBGRA_8888_SkColorType, pack_unpremul_bgra }, 454cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}; 464cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org 477715e06b68a1f07f07d23c63e7128d32654e30e9robertphillipsstatic void fill_canvas(SkCanvas* canvas, SkColorType colorType, PackUnpremulProc proc) { 484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org // Don't strictly need a bitmap, but its a handy way to allocate the pixels 49a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com SkBitmap bmp; 50deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org bmp.allocN32Pixels(256, 256); 51a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com 52a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com for (int a = 0; a < 256; ++a) { 534cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org uint32_t* pixels = bmp.getAddr32(0, a); 54a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com for (int r = 0; r < 256; ++r) { 554cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org pixels[r] = proc(SkColorSetARGB(a, r, 0, 0)); 56a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com } 57a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com } 58a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com 59e5ea500d4714a7d84de2bf913e81be3b65d2de68reed const SkImageInfo info = SkImageInfo::Make(bmp.width(), bmp.height(), 60e5ea500d4714a7d84de2bf913e81be3b65d2de68reed colorType, kUnpremul_SkAlphaType); 614cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org canvas->writePixels(info, bmp.getPixels(), bmp.rowBytes(), 0, 0); 624cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org} 63a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com 647715e06b68a1f07f07d23c63e7128d32654e30e9robertphillipsstatic void test_premul_alpha_roundtrip(skiatest::Reporter* reporter, SkSurface* surf) { 657715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips SkCanvas* canvas = surf->getCanvas(); 661530283c483cb88aa725bce50a6d193dd00ee570kkinnunen for (size_t upmaIdx = 0; upmaIdx < SK_ARRAY_COUNT(gUnpremul); ++upmaIdx) { 677715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips fill_canvas(canvas, gUnpremul[upmaIdx].fColorType, gUnpremul[upmaIdx].fPackProc); 681530283c483cb88aa725bce50a6d193dd00ee570kkinnunen 691530283c483cb88aa725bce50a6d193dd00ee570kkinnunen const SkImageInfo info = SkImageInfo::Make(256, 256, gUnpremul[upmaIdx].fColorType, 701530283c483cb88aa725bce50a6d193dd00ee570kkinnunen kUnpremul_SkAlphaType); 711530283c483cb88aa725bce50a6d193dd00ee570kkinnunen SkBitmap readBmp1; 721530283c483cb88aa725bce50a6d193dd00ee570kkinnunen readBmp1.allocPixels(info); 731530283c483cb88aa725bce50a6d193dd00ee570kkinnunen SkBitmap readBmp2; 741530283c483cb88aa725bce50a6d193dd00ee570kkinnunen readBmp2.allocPixels(info); 751530283c483cb88aa725bce50a6d193dd00ee570kkinnunen 761530283c483cb88aa725bce50a6d193dd00ee570kkinnunen readBmp1.eraseColor(0); 771530283c483cb88aa725bce50a6d193dd00ee570kkinnunen readBmp2.eraseColor(0); 781530283c483cb88aa725bce50a6d193dd00ee570kkinnunen 7912e946b4bfdf598bffb276776ea6e25439e25265Mike Reed canvas->readPixels(readBmp1, 0, 0); 807715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips sk_tool_utils::write_pixels(canvas, readBmp1, 0, 0, gUnpremul[upmaIdx].fColorType, 811530283c483cb88aa725bce50a6d193dd00ee570kkinnunen kUnpremul_SkAlphaType); 8212e946b4bfdf598bffb276776ea6e25439e25265Mike Reed canvas->readPixels(readBmp2, 0, 0); 831530283c483cb88aa725bce50a6d193dd00ee570kkinnunen 841530283c483cb88aa725bce50a6d193dd00ee570kkinnunen bool success = true; 851530283c483cb88aa725bce50a6d193dd00ee570kkinnunen for (int y = 0; y < 256 && success; ++y) { 861530283c483cb88aa725bce50a6d193dd00ee570kkinnunen const uint32_t* pixels1 = readBmp1.getAddr32(0, y); 871530283c483cb88aa725bce50a6d193dd00ee570kkinnunen const uint32_t* pixels2 = readBmp2.getAddr32(0, y); 881530283c483cb88aa725bce50a6d193dd00ee570kkinnunen for (int x = 0; x < 256 && success; ++x) { 891530283c483cb88aa725bce50a6d193dd00ee570kkinnunen // We see sporadic failures here. May help to see where it goes wrong. 901530283c483cb88aa725bce50a6d193dd00ee570kkinnunen if (pixels1[x] != pixels2[x]) { 911530283c483cb88aa725bce50a6d193dd00ee570kkinnunen SkDebugf("%x != %x, x = %d, y = %d\n", pixels1[x], pixels2[x], x, y); 92a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com } 931530283c483cb88aa725bce50a6d193dd00ee570kkinnunen REPORTER_ASSERT(reporter, success = pixels1[x] == pixels2[x]); 94a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com } 95a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com } 96a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com } 97a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com} 981530283c483cb88aa725bce50a6d193dd00ee570kkinnunen 991530283c483cb88aa725bce50a6d193dd00ee570kkinnunenDEF_TEST(PremulAlphaRoundTrip, reporter) { 1001530283c483cb88aa725bce50a6d193dd00ee570kkinnunen const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256); 1017715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips 1027715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips sk_sp<SkSurface> surf(SkSurface::MakeRaster(info)); 1037715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips 1047715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips test_premul_alpha_roundtrip(reporter, surf.get()); 1051530283c483cb88aa725bce50a6d193dd00ee570kkinnunen} 1061530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#if SK_SUPPORT_GPU 10768d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(PremulAlphaRoundTrip_Gpu, reporter, ctxInfo) { 1081530283c483cb88aa725bce50a6d193dd00ee570kkinnunen const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256); 1097715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips 1108b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(ctxInfo.grContext(), 1117715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips SkBudgeted::kNo, 1127715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips info)); 1137715e06b68a1f07f07d23c63e7128d32654e30e9robertphillips test_premul_alpha_roundtrip(reporter, surf.get()); 1141530283c483cb88aa725bce50a6d193dd00ee570kkinnunen} 1151530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#endif 116