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 = SkIRect::MakeWH(info.width(), info.height());
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(SkSurface::NewRenderTarget(context, info));
119    SkAutoTUnref<SkSurface> destinationSurface(SkSurface::NewRenderTarget(context, info));
120
121    runShaderTest(reporter, sourceSurface.get(), destinationSurface.get(), info);
122}
123
124void gpuToRaster(skiatest::Reporter* reporter, GrContext* context) {
125    SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
126
127    SkAutoTUnref<SkSurface> sourceSurface(SkSurface::NewRenderTarget(context, info));
128    SkAutoTUnref<SkSurface> destinationSurface(SkSurface::NewRaster(info));
129
130    runShaderTest(reporter, sourceSurface.get(), destinationSurface.get(), info);
131}
132
133void rasterToGpu(skiatest::Reporter* reporter, GrContext* context) {
134    SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
135
136    SkAutoTUnref<SkSurface> sourceSurface(SkSurface::NewRaster(info));
137    SkAutoTUnref<SkSurface> destinationSurface(SkSurface::NewRenderTarget(context, info));
138
139    runShaderTest(reporter, sourceSurface.get(), destinationSurface.get(), info);
140}
141
142DEF_GPUTEST(ImageNewShader_GPU, reporter, factory) {
143    for (int i = 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
144        GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
145
146        if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
147            continue;
148        }
149
150        GrContext* context = factory->get(glCtxType);
151
152        if (NULL == context) {
153            continue;
154        }
155
156        //  GPU -> GPU
157        gpuToGpu(reporter, context);
158
159        //  GPU -> RASTER
160        gpuToRaster(reporter, context);
161
162        //  RASTER -> GPU
163        rasterToGpu(reporter, context);
164    }
165}
166
167#endif
168