1/*
2 * Copyright 2014 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
8#include "SkCanvas.h"
9#include "SkImage.h"
10#include "SkShader.h"
11#include "SkSurface.h"
12#include "SkTypes.h"
13#include "Test.h"
14
15#if SK_SUPPORT_GPU
16#include "GrContext.h"
17#endif
18
19static void test_bitmap_equality(skiatest::Reporter* reporter, SkBitmap& bm1, SkBitmap& bm2) {
20    REPORTER_ASSERT(reporter, bm1.computeByteSize() == bm2.computeByteSize());
21    REPORTER_ASSERT(reporter, 0 == memcmp(bm1.getPixels(), bm2.getPixels(), bm1.computeByteSize()));
22}
23
24static void paint_source(SkSurface* sourceSurface) {
25    SkCanvas* sourceCanvas = sourceSurface->getCanvas();
26    sourceCanvas->clear(0xFFDEDEDE);
27
28    SkPaint paintColor;
29    paintColor.setColor(0xFFFF0000);
30    paintColor.setStyle(SkPaint::kFill_Style);
31
32    SkRect rect = SkRect::MakeXYWH(
33            SkIntToScalar(1),
34            SkIntToScalar(0),
35            SkIntToScalar(1),
36            SkIntToScalar(sourceSurface->height()));
37
38    sourceCanvas->drawRect(rect, paintColor);
39}
40
41static void run_shader_test(skiatest::Reporter* reporter, SkSurface* sourceSurface,
42                            SkSurface* destinationSurface, SkImageInfo& info) {
43    paint_source(sourceSurface);
44
45    sk_sp<SkImage> sourceImage(sourceSurface->makeImageSnapshot());
46    sk_sp<SkShader> sourceShader = sourceImage->makeShader(
47            SkShader::kRepeat_TileMode,
48            SkShader::kRepeat_TileMode);
49
50    SkPaint paint;
51    paint.setShader(sourceShader);
52
53    SkCanvas* destinationCanvas = destinationSurface->getCanvas();
54    destinationCanvas->clear(SK_ColorTRANSPARENT);
55    destinationCanvas->drawPaint(paint);
56
57    SkBitmap bmOrig;
58    bmOrig.allocN32Pixels(info.width(), info.height());
59    sourceSurface->readPixels(bmOrig, 0, 0);
60
61
62    SkBitmap bm;
63    bm.allocN32Pixels(info.width(), info.height());
64    destinationSurface->readPixels(bm, 0, 0);
65
66    test_bitmap_equality(reporter, bmOrig, bm);
67
68    // Test with a translated shader
69    SkMatrix matrix;
70    matrix.setTranslate(SkIntToScalar(-1), SkIntToScalar(0));
71
72    sk_sp<SkShader> sourceShaderTranslated = sourceImage->makeShader(
73            SkShader::kRepeat_TileMode,
74            SkShader::kRepeat_TileMode,
75            &matrix);
76
77    destinationCanvas->clear(SK_ColorTRANSPARENT);
78
79    SkPaint paintTranslated;
80    paintTranslated.setShader(sourceShaderTranslated);
81
82    destinationCanvas->drawPaint(paintTranslated);
83
84    SkBitmap bmt;
85    bmt.allocN32Pixels(info.width(), info.height());
86    destinationSurface->readPixels(bmt, 0, 0);
87
88    //  Test correctness
89    {
90        for (int y = 0; y < info.height(); y++) {
91            REPORTER_ASSERT(reporter, 0xFFFF0000 == bmt.getColor(0, y));
92
93            for (int x = 1; x < info.width(); x++) {
94                REPORTER_ASSERT(reporter, 0xFFDEDEDE == bmt.getColor(x, y));
95            }
96        }
97    }
98}
99
100DEF_TEST(ImageNewShader, reporter) {
101    SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
102
103    auto sourceSurface(SkSurface::MakeRaster(info));
104    auto destinationSurface(SkSurface::MakeRaster(info));
105
106    run_shader_test(reporter, sourceSurface.get(), destinationSurface.get(), info);
107}
108
109#if SK_SUPPORT_GPU
110
111static void gpu_to_gpu(skiatest::Reporter* reporter, GrContext* context) {
112    SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
113
114    auto sourceSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info));
115    auto destinationSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info));
116
117    run_shader_test(reporter, sourceSurface.get(), destinationSurface.get(), info);
118}
119
120static void gpu_to_raster(skiatest::Reporter* reporter, GrContext* context) {
121    SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
122
123    auto sourceSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info));
124    auto destinationSurface(SkSurface::MakeRaster(info));
125
126    run_shader_test(reporter, sourceSurface.get(), destinationSurface.get(), info);
127}
128
129static void raster_to_gpu(skiatest::Reporter* reporter, GrContext* context) {
130    SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
131
132    auto sourceSurface(SkSurface::MakeRaster(info));
133    auto destinationSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info));
134
135    run_shader_test(reporter, sourceSurface.get(), destinationSurface.get(), info);
136}
137
138DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageNewShader_GPU, reporter, ctxInfo) {
139    //  GPU -> GPU
140    gpu_to_gpu(reporter, ctxInfo.grContext());
141
142    //  GPU -> RASTER
143    gpu_to_raster(reporter, ctxInfo.grContext());
144
145    //  RASTER -> GPU
146    raster_to_gpu(reporter, ctxInfo.grContext());
147}
148
149#endif
150