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 "SkTypes.h"
9#if SK_SUPPORT_GPU
10#include "GrContextFactory.h"
11#endif
12#include "SkCanvas.h"
13#include "SkImage.h"
14#include "SkShader.h"
15#include "SkSurface.h"
16
17#include "Test.h"
18
19void testBitmapEquality(skiatest::Reporter* reporter, SkBitmap& bm1, SkBitmap& bm2) {
20    SkAutoLockPixels lockBm1(bm1);
21    SkAutoLockPixels lockBm2(bm2);
22
23    REPORTER_ASSERT(reporter, bm1.getSize() == bm2.getSize());
24    REPORTER_ASSERT(reporter, 0 == memcmp(bm1.getPixels(), bm2.getPixels(), bm1.getSize()));
25}
26
27void paintSource(SkSurface* sourceSurface) {
28    SkCanvas* sourceCanvas = sourceSurface->getCanvas();
29    sourceCanvas->clear(0xFFDEDEDE);
30
31    SkPaint paintColor;
32    paintColor.setColor(0xFFFF0000);
33    paintColor.setStyle(SkPaint::kFill_Style);
34
35    SkRect rect = SkRect::MakeXYWH(
36            SkIntToScalar(1),
37            SkIntToScalar(0),
38            SkIntToScalar(1),
39            SkIntToScalar(sourceSurface->height()));
40
41    sourceCanvas->drawRect(rect, paintColor);
42}
43
44void runShaderTest(skiatest::Reporter* reporter, SkSurface* sourceSurface, SkSurface* destinationSurface, SkImageInfo& info) {
45    paintSource(sourceSurface);
46
47    SkAutoTUnref<SkImage> sourceImage(sourceSurface->newImageSnapshot());
48    SkAutoTUnref<SkShader> sourceShader(sourceImage->newShader(
49            SkShader::kRepeat_TileMode,
50            SkShader::kRepeat_TileMode));
51
52    SkPaint paint;
53    paint.setShader(sourceShader);
54
55    SkCanvas* destinationCanvas = destinationSurface->getCanvas();
56    destinationCanvas->clear(SK_ColorTRANSPARENT);
57    destinationCanvas->drawPaint(paint);
58
59    SkIRect rect = info.bounds();
60
61    SkBitmap bmOrig;
62    sourceSurface->getCanvas()->readPixels(rect, &bmOrig);
63
64
65    SkBitmap bm;
66    destinationCanvas->readPixels(rect, &bm);
67
68    testBitmapEquality(reporter, bmOrig, bm);
69
70
71
72    // Test with a translated shader
73    SkMatrix matrix;
74    matrix.setTranslate(SkIntToScalar(-1), SkIntToScalar(0));
75
76    SkAutoTUnref<SkShader> sourceShaderTranslated(sourceImage->newShader(
77            SkShader::kRepeat_TileMode,
78            SkShader::kRepeat_TileMode,
79            &matrix));
80
81    destinationCanvas->clear(SK_ColorTRANSPARENT);
82
83    SkPaint paintTranslated;
84    paintTranslated.setShader(sourceShaderTranslated);
85
86    destinationCanvas->drawPaint(paintTranslated);
87
88    SkBitmap bmt;
89    destinationCanvas->readPixels(rect, &bmt);
90
91    //  Test correctness
92    {
93        SkAutoLockPixels lockBm(bmt);
94        for (int y = 0; y < info.height(); y++) {
95            REPORTER_ASSERT(reporter, 0xFFFF0000 == bmt.getColor(0, y));
96
97            for (int x = 1; x < info.width(); x++) {
98                REPORTER_ASSERT(reporter, 0xFFDEDEDE == bmt.getColor(x, y));
99            }
100        }
101    }
102}
103
104DEF_TEST(ImageNewShader, reporter) {
105    SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
106
107    SkAutoTUnref<SkSurface> sourceSurface(SkSurface::NewRaster(info));
108    SkAutoTUnref<SkSurface> destinationSurface(SkSurface::NewRaster(info));
109
110    runShaderTest(reporter, sourceSurface.get(), destinationSurface.get(), info);
111}
112
113#if SK_SUPPORT_GPU
114
115void gpuToGpu(skiatest::Reporter* reporter, GrContext* context) {
116    SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
117
118    SkAutoTUnref<SkSurface> sourceSurface(
119        SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info));
120    SkAutoTUnref<SkSurface> destinationSurface(
121        SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info));
122
123    runShaderTest(reporter, sourceSurface.get(), destinationSurface.get(), info);
124}
125
126void gpuToRaster(skiatest::Reporter* reporter, GrContext* context) {
127    SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
128
129    SkAutoTUnref<SkSurface> sourceSurface(SkSurface::NewRenderTarget(context,
130        SkSurface::kNo_Budgeted, info));
131    SkAutoTUnref<SkSurface> destinationSurface(SkSurface::NewRaster(info));
132
133    runShaderTest(reporter, sourceSurface.get(), destinationSurface.get(), info);
134}
135
136void rasterToGpu(skiatest::Reporter* reporter, GrContext* context) {
137    SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
138
139    SkAutoTUnref<SkSurface> sourceSurface(SkSurface::NewRaster(info));
140    SkAutoTUnref<SkSurface> destinationSurface(SkSurface::NewRenderTarget(context,
141        SkSurface::kNo_Budgeted, info));
142
143    runShaderTest(reporter, sourceSurface.get(), destinationSurface.get(), info);
144}
145
146DEF_GPUTEST(ImageNewShader_GPU, reporter, factory) {
147    for (int i = 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
148        GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
149
150        if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
151            continue;
152        }
153
154        GrContext* context = factory->get(glCtxType);
155
156        if (NULL == context) {
157            continue;
158        }
159
160        //  GPU -> GPU
161        gpuToGpu(reporter, context);
162
163        //  GPU -> RASTER
164        gpuToRaster(reporter, context);
165
166        //  RASTER -> GPU
167        rasterToGpu(reporter, context);
168    }
169}
170
171#endif
172