aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/PremulAlphaRoundTripTest.cpp
blob: 9f5d6ff3388f88ac61346094b52d8f89ce89d3b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBitmapDevice.h"
#include "SkCanvas.h"
#include "SkConfig8888.h"
#include "Test.h"
#include "sk_tool_utils.h"

#if SK_SUPPORT_GPU
#include "GrContextFactory.h"
#include "SkGpuDevice.h"
#endif

static uint32_t pack_unpremul_rgba(SkColor c) {
    uint32_t packed;
    uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
    byte[0] = SkColorGetR(c);
    byte[1] = SkColorGetG(c);
    byte[2] = SkColorGetB(c);
    byte[3] = SkColorGetA(c);
    return packed;
}

static uint32_t pack_unpremul_bgra(SkColor c) {
    uint32_t packed;
    uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
    byte[0] = SkColorGetB(c);
    byte[1] = SkColorGetG(c);
    byte[2] = SkColorGetR(c);
    byte[3] = SkColorGetA(c);
    return packed;
}

typedef uint32_t (*PackUnpremulProc)(SkColor);

const struct {
    SkColorType         fColorType;
    PackUnpremulProc    fPackProc;
} gUnpremul[] = {
    { kRGBA_8888_SkColorType, pack_unpremul_rgba },
    { kBGRA_8888_SkColorType, pack_unpremul_bgra },
};

static void fillCanvas(SkCanvas* canvas, SkColorType colorType, PackUnpremulProc proc) {
    // Don't strictly need a bitmap, but its a handy way to allocate the pixels
    SkBitmap bmp;
    bmp.allocN32Pixels(256, 256);

    for (int a = 0; a < 256; ++a) {
        uint32_t* pixels = bmp.getAddr32(0, a);
        for (int r = 0; r < 256; ++r) {
            pixels[r] = proc(SkColorSetARGB(a, r, 0, 0));
        }
    }

    const SkImageInfo info = SkImageInfo::Make(bmp.width(), bmp.height(),
                                               colorType, kUnpremul_SkAlphaType);
    canvas->writePixels(info, bmp.getPixels(), bmp.rowBytes(), 0, 0);
}

DEF_GPUTEST(PremulAlphaRoundTrip, reporter, factory) {
    const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);

    for (int dtype = 0; dtype < 2; ++dtype) {

        int glCtxTypeCnt = 1;
#if SK_SUPPORT_GPU
        if (0 != dtype)  {
            glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
        }
#endif
        for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
            SkAutoTUnref<SkBaseDevice> device;
            if (0 == dtype) {
                device.reset(SkBitmapDevice::Create(info));
            } else {
#if SK_SUPPORT_GPU
                GrContextFactory::GLContextType type =
                    static_cast<GrContextFactory::GLContextType>(glCtxType);
                if (!GrContextFactory::IsRenderingGLContext(type)) {
                    continue;
                }
                GrContext* ctx = factory->get(type);
                if (NULL == ctx) {
                    continue;
                }
                SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
                device.reset(SkGpuDevice::Create(ctx, SkSurface::kNo_Budgeted, info, 0, &props));
#else
                continue;
#endif
            }
            SkCanvas canvas(device);

            for (size_t upmaIdx = 0; upmaIdx < SK_ARRAY_COUNT(gUnpremul); ++upmaIdx) {
                fillCanvas(&canvas, gUnpremul[upmaIdx].fColorType, gUnpremul[upmaIdx].fPackProc);

                const SkImageInfo info = SkImageInfo::Make(256, 256, gUnpremul[upmaIdx].fColorType,
                                                           kUnpremul_SkAlphaType);
                SkBitmap readBmp1;
                readBmp1.allocPixels(info);
                SkBitmap readBmp2;
                readBmp2.allocPixels(info);

                readBmp1.eraseColor(0);
                readBmp2.eraseColor(0);

                canvas.readPixels(&readBmp1, 0, 0);
                sk_tool_utils::write_pixels(&canvas, readBmp1, 0, 0, gUnpremul[upmaIdx].fColorType,
                                            kUnpremul_SkAlphaType);
                canvas.readPixels(&readBmp2, 0, 0);

                bool success = true;
                for (int y = 0; y < 256 && success; ++y) {
                    const uint32_t* pixels1 = readBmp1.getAddr32(0, y);
                    const uint32_t* pixels2 = readBmp2.getAddr32(0, y);
                    for (int x = 0; x < 256 && success; ++x) {
                        // We see sporadic failures here. May help to see where it goes wrong.
                        if (pixels1[x] != pixels2[x]) {
                            SkDebugf("%x != %x, x = %d, y = %d\n", pixels1[x], pixels2[x], x, y);
                        }
                        REPORTER_ASSERT(reporter, success = pixels1[x] == pixels2[x]);
                    }
                }
            }
        }
    }
}