• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 // This is a GPU-backend specific test. It relies on static intializers to work
9 
10 #include "SkTypes.h"
11 
12 #if SK_SUPPORT_GPU
13 
14 #include "GrContextFactory.h"
15 #include "GrContextPriv.h"
16 #include "GrGpu.h"
17 #include "GrResourceProvider.h"
18 #include "GrSurfaceProxy.h"
19 #include "GrTexture.h"
20 #include "GrTest.h"
21 #include "SkGr.h"
22 #include "SkSurface.h"
23 #include "Test.h"
24 
25 using sk_gpu_test::GrContextFactory;
26 
fill_transfer_data(int left,int top,int width,int height,int bufferWidth,GrColor * data)27 void fill_transfer_data(int left, int top, int width, int height, int bufferWidth,
28                         GrColor* data) {
29 
30     // build red-green gradient
31     for (int j = top; j < top + height; ++j) {
32         for (int i = left; i < left + width; ++i) {
33             unsigned int red = (unsigned int)(256.f*((i - left) / (float)width));
34             unsigned int green = (unsigned int)(256.f*((j - top) / (float)height));
35             data[i + j*bufferWidth] = GrColorPackRGBA(red - (red>>8),
36                                                       green - (green>>8), 0xff, 0xff);
37         }
38     }
39 }
40 
does_full_buffer_contain_correct_values(GrColor * srcBuffer,GrColor * dstBuffer,int width,int height,int bufferWidth,int bufferHeight,GrSurfaceOrigin origin)41 bool does_full_buffer_contain_correct_values(GrColor* srcBuffer,
42                                              GrColor* dstBuffer,
43                                              int width,
44                                              int height,
45                                              int bufferWidth,
46                                              int bufferHeight,
47                                              GrSurfaceOrigin origin) {
48     GrColor* srcPtr = srcBuffer;
49     bool bottomUp = SkToBool(kBottomLeft_GrSurfaceOrigin == origin);
50     GrColor* dstPtr = bottomUp ? dstBuffer + bufferWidth*(bufferHeight-1) : dstBuffer;
51     int dstIncrement = bottomUp ? -bufferWidth : +bufferWidth;
52 
53     for (int j = 0; j < height; ++j) {
54         for (int i = 0; i < width; ++i) {
55             if (srcPtr[i] != dstPtr[i]) {
56                 return false;
57             }
58         }
59         srcPtr += bufferWidth;
60         dstPtr += dstIncrement;
61     }
62     return true;
63 }
64 
basic_transfer_test(skiatest::Reporter * reporter,GrContext * context,GrPixelConfig config,GrSurfaceOrigin origin,bool renderTarget)65 void basic_transfer_test(skiatest::Reporter* reporter, GrContext* context, GrPixelConfig config,
66                          GrSurfaceOrigin origin, bool renderTarget) {
67     if (GrCaps::kNone_MapFlags == context->caps()->mapBufferFlags()) {
68         return;
69     }
70 
71     auto resourceProvider = context->contextPriv().resourceProvider();
72     GrGpu* gpu = context->contextPriv().getGpu();
73 
74     if (!gpu->caps()->isConfigTexturable(config)) {
75         return;
76     }
77     if (renderTarget && !gpu->caps()->isConfigRenderable(config, false)) {
78         return;
79     }
80 
81     // set up the data
82     const int kTextureWidth = 16;
83     const int kTextureHeight = 16;
84     const int kBufferWidth = 20;
85     const int kBufferHeight = 16;
86     size_t rowBytes = kBufferWidth * sizeof(GrColor);
87     SkAutoTMalloc<GrColor> srcBuffer(kBufferWidth*kBufferHeight);
88     SkAutoTMalloc<GrColor> dstBuffer(kBufferWidth*kBufferHeight);
89 
90     fill_transfer_data(0, 0, kTextureWidth, kTextureHeight, kBufferWidth, srcBuffer.get());
91 
92     // create and fill transfer buffer
93     size_t size = rowBytes*kBufferHeight;
94     uint32_t bufferFlags = GrResourceProvider::kNoPendingIO_Flag;
95     sk_sp<GrBuffer> buffer(resourceProvider->createBuffer(size,
96                                                           kXferCpuToGpu_GrBufferType,
97                                                           kDynamic_GrAccessPattern,
98                                                           bufferFlags));
99     if (!buffer) {
100         return;
101     }
102 
103     void* data = buffer->map();
104     memcpy(data, srcBuffer.get(), size);
105     buffer->unmap();
106 
107     // create texture
108     GrSurfaceDesc desc;
109     desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
110     desc.fOrigin = origin;
111     desc.fWidth = kTextureWidth;
112     desc.fHeight = kTextureHeight;
113     desc.fConfig = config;
114     desc.fSampleCnt = 1;
115     sk_sp<GrTexture> tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
116 
117     //////////////////////////
118     // transfer full data
119 
120     bool result;
121     result = gpu->transferPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight,
122                                  config, buffer.get(), 0, rowBytes);
123     REPORTER_ASSERT(reporter, result);
124 
125     memset(dstBuffer.get(), 0xCDCD, size);
126     result = gpu->readPixels(tex.get(), origin, 0, 0, kTextureWidth, kTextureHeight,
127                              config, dstBuffer.get(), rowBytes);
128     if (result) {
129         REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
130                                                                           dstBuffer,
131                                                                           kTextureWidth,
132                                                                           kTextureHeight,
133                                                                           kBufferWidth,
134                                                                           kBufferHeight,
135                                                                           origin));
136     }
137 
138     //////////////////////////
139     // transfer partial data
140 
141     const int kLeft = 2;
142     const int kTop = 10;
143     const int kWidth = 10;
144     const int kHeight = 2;
145 
146     // change color of subrectangle
147     fill_transfer_data(kLeft, kTop, kWidth, kHeight, kBufferWidth, srcBuffer.get());
148     data = buffer->map();
149     memcpy(data, srcBuffer.get(), size);
150     buffer->unmap();
151 
152     size_t offset = sizeof(GrColor)*(kTop*kBufferWidth + kLeft);
153     result = gpu->transferPixels(tex.get(), kLeft, kTop, kWidth, kHeight, config,
154                                  buffer.get(), offset, rowBytes);
155     REPORTER_ASSERT(reporter, result);
156 
157     memset(dstBuffer.get(), 0xCDCD, size);
158     result = gpu->readPixels(tex.get(), origin, 0, 0, kTextureWidth, kTextureHeight,
159                              config, dstBuffer.get(), rowBytes);
160     if (result) {
161         REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
162                                                                           dstBuffer,
163                                                                           kTextureWidth,
164                                                                           kTextureHeight,
165                                                                           kBufferWidth,
166                                                                           kBufferHeight,
167                                                                           origin));
168     }
169 }
170 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TransferPixelsTest,reporter,ctxInfo)171 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TransferPixelsTest, reporter, ctxInfo) {
172     // RGBA
173     basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
174                         kTopLeft_GrSurfaceOrigin, false);
175     basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
176                         kTopLeft_GrSurfaceOrigin, true);
177     basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
178                         kBottomLeft_GrSurfaceOrigin, false);
179     basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
180                         kBottomLeft_GrSurfaceOrigin, true);
181 
182     // BGRA
183     basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
184                         kTopLeft_GrSurfaceOrigin, false);
185     basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
186                         kTopLeft_GrSurfaceOrigin, true);
187     basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
188                         kBottomLeft_GrSurfaceOrigin, false);
189     basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
190                         kBottomLeft_GrSurfaceOrigin, true);
191 }
192 
193 #endif
194