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
84ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "SkBitmapDevice.h"
9a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkCanvas.h"
10a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkConfig8888.h"
114ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "Test.h"
124cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org#include "sk_tool_utils.h"
13cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
14cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
1567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#include "GrContextFactory.h"
16a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkGpuDevice.h"
17cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
18a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
194cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgstatic uint32_t pack_unpremul_rgba(SkColor c) {
204cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    uint32_t packed;
214cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
224cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    byte[0] = SkColorGetR(c);
234cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    byte[1] = SkColorGetG(c);
244cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    byte[2] = SkColorGetB(c);
254cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    byte[3] = SkColorGetA(c);
264cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return packed;
274cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
284cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
294cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgstatic uint32_t pack_unpremul_bgra(SkColor c) {
304cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    uint32_t packed;
314cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
324cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    byte[0] = SkColorGetB(c);
334cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    byte[1] = SkColorGetG(c);
344cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    byte[2] = SkColorGetR(c);
354cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    byte[3] = SkColorGetA(c);
364cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return packed;
374cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
384cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
394cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgtypedef uint32_t (*PackUnpremulProc)(SkColor);
404cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
414cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgconst struct {
42a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkColorType         fColorType;
43a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    PackUnpremulProc    fPackProc;
444cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org} gUnpremul[] = {
45a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    { kRGBA_8888_SkColorType, pack_unpremul_rgba },
46a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    { kBGRA_8888_SkColorType, pack_unpremul_bgra },
474cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org};
484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
494cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgstatic void fillCanvas(SkCanvas* canvas, SkColorType colorType, PackUnpremulProc proc) {
504cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // Don't strictly need a bitmap, but its a handy way to allocate the pixels
51a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    SkBitmap bmp;
52deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    bmp.allocN32Pixels(256, 256);
53a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
54a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    for (int a = 0; a < 256; ++a) {
554cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        uint32_t* pixels = bmp.getAddr32(0, a);
56a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        for (int r = 0; r < 256; ++r) {
574cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            pixels[r] = proc(SkColorSetARGB(a, r, 0, 0));
58a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        }
59a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
60a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
61e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = SkImageInfo::Make(bmp.width(), bmp.height(),
62e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                                               colorType, kUnpremul_SkAlphaType);
634cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    canvas->writePixels(info, bmp.getPixels(), bmp.rowBytes(), 0, 0);
644cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
65a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
664ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.orgDEF_GPUTEST(PremulAlphaRoundTrip, reporter, factory) {
6715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
6815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org
69a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    for (int dtype = 0; dtype < 2; ++dtype) {
7067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com
7167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        int glCtxTypeCnt = 1;
7267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#if SK_SUPPORT_GPU
7367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        if (0 != dtype)  {
7467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
7567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        }
7667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#endif
7767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com        for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
78184ff37c625f8a0588c6e27a24d2284bd70593dfmtklein            SkAutoTUnref<SkBaseDevice> device;
7967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            if (0 == dtype) {
8015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                device.reset(SkBitmapDevice::Create(info));
8167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            } else {
8267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com#if SK_SUPPORT_GPU
8367b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                GrContextFactory::GLContextType type =
8467b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    static_cast<GrContextFactory::GLContextType>(glCtxType);
8567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                if (!GrContextFactory::IsRenderingGLContext(type)) {
8667b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    continue;
8767b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                }
88afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                GrContext* ctx = factory->get(type);
89afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                if (NULL == ctx) {
9067b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    continue;
9167b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                }
92afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
93afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                device.reset(SkGpuDevice::Create(ctx, SkSurface::kNo_Budgeted, info, 0, &props));
94cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
9567b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                continue;
96cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
97a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            }
9867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com            SkCanvas canvas(device);
9967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com
1004cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            for (size_t upmaIdx = 0; upmaIdx < SK_ARRAY_COUNT(gUnpremul); ++upmaIdx) {
1014cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                fillCanvas(&canvas, gUnpremul[upmaIdx].fColorType, gUnpremul[upmaIdx].fPackProc);
102e62513fb9274b65bcd9fecf61acc418dd3949df5skia.committer@gmail.com
103a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                const SkImageInfo info = SkImageInfo::Make(256, 256, gUnpremul[upmaIdx].fColorType,
104a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                                                           kUnpremul_SkAlphaType);
105a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                SkBitmap readBmp1;
106a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                readBmp1.allocPixels(info);
107a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                SkBitmap readBmp2;
108a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                readBmp2.allocPixels(info);
109a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
1104cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                readBmp1.eraseColor(0);
1114cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                readBmp2.eraseColor(0);
11267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com
113a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                canvas.readPixels(&readBmp1, 0, 0);
1144cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                sk_tool_utils::write_pixels(&canvas, readBmp1, 0, 0, gUnpremul[upmaIdx].fColorType,
1154cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                                            kUnpremul_SkAlphaType);
116a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org                canvas.readPixels(&readBmp2, 0, 0);
117a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
11867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                bool success = true;
11967b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                for (int y = 0; y < 256 && success; ++y) {
1204cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                    const uint32_t* pixels1 = readBmp1.getAddr32(0, y);
1214cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                    const uint32_t* pixels2 = readBmp2.getAddr32(0, y);
12267b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    for (int x = 0; x < 256 && success; ++x) {
123e83909f76c435176b298a2033a0852d1fbd98df4mtklein                        // We see sporadic failures here. May help to see where it goes wrong.
124e83909f76c435176b298a2033a0852d1fbd98df4mtklein                        if (pixels1[x] != pixels2[x]) {
125e83909f76c435176b298a2033a0852d1fbd98df4mtklein                            SkDebugf("%x != %x, x = %d, y = %d\n", pixels1[x], pixels2[x], x, y);
126e83909f76c435176b298a2033a0852d1fbd98df4mtklein                        }
1274cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                        REPORTER_ASSERT(reporter, success = pixels1[x] == pixels2[x]);
12867b915de99e6b89d476907930ac8c27afb64d10ebsalomon@google.com                    }
129a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                }
130a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            }
131a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        }
132a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
133a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
134