blob: 050080ac6909c6330a2d0684e5e2174549ed455a [file] [log] [blame]
Jim Van Verth2e5eaf02017-06-21 15:55:46 -04001/*
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
Jim Van Verth2e5eaf02017-06-21 15:55:46 -040012#include "GrContextFactory.h"
13#include "GrContextPriv.h"
14#include "GrGpu.h"
15#include "GrResourceProvider.h"
16#include "GrSurfaceProxy.h"
17#include "GrTexture.h"
18#include "GrTest.h"
19#include "SkGr.h"
20#include "SkSurface.h"
21#include "Test.h"
22
23using sk_gpu_test::GrContextFactory;
24
25void fill_transfer_data(int left, int top, int width, int height, int bufferWidth,
26 GrColor* data) {
27
28 // build red-green gradient
29 for (int j = top; j < top + height; ++j) {
30 for (int i = left; i < left + width; ++i) {
31 unsigned int red = (unsigned int)(256.f*((i - left) / (float)width));
32 unsigned int green = (unsigned int)(256.f*((j - top) / (float)height));
33 data[i + j*bufferWidth] = GrColorPackRGBA(red - (red>>8),
34 green - (green>>8), 0xff, 0xff);
35 }
36 }
37}
38
39bool does_full_buffer_contain_correct_values(GrColor* srcBuffer,
40 GrColor* dstBuffer,
41 int width,
42 int height,
43 int bufferWidth,
Brian Salomona6948702018-06-01 15:33:20 -040044 int bufferHeight) {
Jim Van Verth2e5eaf02017-06-21 15:55:46 -040045 GrColor* srcPtr = srcBuffer;
Brian Salomona6948702018-06-01 15:33:20 -040046 GrColor* dstPtr = dstBuffer;
Jim Van Verth2e5eaf02017-06-21 15:55:46 -040047
48 for (int j = 0; j < height; ++j) {
49 for (int i = 0; i < width; ++i) {
50 if (srcPtr[i] != dstPtr[i]) {
51 return false;
52 }
53 }
54 srcPtr += bufferWidth;
Brian Salomona6948702018-06-01 15:33:20 -040055 dstPtr += bufferWidth;
Jim Van Verth2e5eaf02017-06-21 15:55:46 -040056 }
57 return true;
58}
59
Brian Salomonc320b152018-02-20 14:05:36 -050060void basic_transfer_test(skiatest::Reporter* reporter, GrContext* context, GrColorType colorType,
Brian Salomona6948702018-06-01 15:33:20 -040061 bool renderTarget) {
Brian Salomonc7fe0f72018-05-11 10:14:21 -040062 if (GrCaps::kNone_MapFlags == context->contextPriv().caps()->mapBufferFlags()) {
Brian Salomon7f56d3d2017-10-09 13:02:49 -040063 return;
64 }
65
Robert Phillips6be756b2018-01-16 15:07:54 -050066 auto resourceProvider = context->contextPriv().resourceProvider();
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050067 GrGpu* gpu = context->contextPriv().getGpu();
Robert Phillips6be756b2018-01-16 15:07:54 -050068
Jim Van Verth2e5eaf02017-06-21 15:55:46 -040069 // set up the data
70 const int kTextureWidth = 16;
71 const int kTextureHeight = 16;
72 const int kBufferWidth = 20;
73 const int kBufferHeight = 16;
74 size_t rowBytes = kBufferWidth * sizeof(GrColor);
75 SkAutoTMalloc<GrColor> srcBuffer(kBufferWidth*kBufferHeight);
76 SkAutoTMalloc<GrColor> dstBuffer(kBufferWidth*kBufferHeight);
77
78 fill_transfer_data(0, 0, kTextureWidth, kTextureHeight, kBufferWidth, srcBuffer.get());
79
80 // create and fill transfer buffer
81 size_t size = rowBytes*kBufferHeight;
82 uint32_t bufferFlags = GrResourceProvider::kNoPendingIO_Flag;
Robert Phillips6be756b2018-01-16 15:07:54 -050083 sk_sp<GrBuffer> buffer(resourceProvider->createBuffer(size,
84 kXferCpuToGpu_GrBufferType,
85 kDynamic_GrAccessPattern,
86 bufferFlags));
Jim Van Verth2e5eaf02017-06-21 15:55:46 -040087 if (!buffer) {
88 return;
89 }
90
91 void* data = buffer->map();
92 memcpy(data, srcBuffer.get(), size);
93 buffer->unmap();
94
Brian Salomonc320b152018-02-20 14:05:36 -050095 for (auto srgbEncoding : {GrSRGBEncoded::kNo, GrSRGBEncoded::kYes}) {
96 // create texture
97 GrSurfaceDesc desc;
98 desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
Brian Salomonc320b152018-02-20 14:05:36 -050099 desc.fWidth = kTextureWidth;
100 desc.fHeight = kTextureHeight;
101 desc.fConfig = GrColorTypeToPixelConfig(colorType, srgbEncoding);
102 desc.fSampleCnt = 1;
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400103
Brian Salomonc320b152018-02-20 14:05:36 -0500104 if (kUnknown_GrPixelConfig == desc.fConfig) {
105 SkASSERT(GrSRGBEncoded::kYes == srgbEncoding);
106 continue;
107 }
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400108
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400109 if (!context->contextPriv().caps()->isConfigTexturable(desc.fConfig) ||
110 (renderTarget && !context->contextPriv().caps()->isConfigRenderable(desc.fConfig))) {
Brian Salomonc320b152018-02-20 14:05:36 -0500111 continue;
112 }
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400113
Brian Salomonc320b152018-02-20 14:05:36 -0500114 sk_sp<GrTexture> tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
Robert Phillips6fc30922018-07-27 12:21:37 -0400115 if (!tex) {
116 continue;
117 }
Robert Phillips16d8ec62017-07-27 16:16:25 -0400118
Brian Salomonc320b152018-02-20 14:05:36 -0500119 //////////////////////////
120 // transfer full data
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400121
Brian Salomonc320b152018-02-20 14:05:36 -0500122 bool result;
123 result = gpu->transferPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight, colorType,
124 buffer.get(), 0, rowBytes);
125 REPORTER_ASSERT(reporter, result);
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400126
Brian Salomonc320b152018-02-20 14:05:36 -0500127 memset(dstBuffer.get(), 0xCDCD, size);
Brian Salomona6948702018-06-01 15:33:20 -0400128 result = gpu->readPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight, colorType,
Brian Salomonc320b152018-02-20 14:05:36 -0500129 dstBuffer.get(), rowBytes);
130 if (result) {
131 REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
132 dstBuffer,
133 kTextureWidth,
134 kTextureHeight,
135 kBufferWidth,
Brian Salomona6948702018-06-01 15:33:20 -0400136 kBufferHeight));
Brian Salomonc320b152018-02-20 14:05:36 -0500137 }
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400138
Brian Salomonc320b152018-02-20 14:05:36 -0500139 //////////////////////////
140 // transfer partial data
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400141
Brian Salomonc320b152018-02-20 14:05:36 -0500142 const int kLeft = 2;
143 const int kTop = 10;
144 const int kWidth = 10;
145 const int kHeight = 2;
146
147 // change color of subrectangle
148 fill_transfer_data(kLeft, kTop, kWidth, kHeight, kBufferWidth, srcBuffer.get());
149 data = buffer->map();
150 memcpy(data, srcBuffer.get(), size);
151 buffer->unmap();
152
153 size_t offset = sizeof(GrColor) * (kTop * kBufferWidth + kLeft);
154 result = gpu->transferPixels(tex.get(), kLeft, kTop, kWidth, kHeight, colorType,
155 buffer.get(), offset, rowBytes);
156 REPORTER_ASSERT(reporter, result);
157
158 memset(dstBuffer.get(), 0xCDCD, size);
Brian Salomona6948702018-06-01 15:33:20 -0400159 result = gpu->readPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight, colorType,
Brian Salomonc320b152018-02-20 14:05:36 -0500160 dstBuffer.get(), rowBytes);
161 if (result) {
162 REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
163 dstBuffer,
164 kTextureWidth,
165 kTextureHeight,
166 kBufferWidth,
Brian Salomona6948702018-06-01 15:33:20 -0400167 kBufferHeight));
Brian Salomonc320b152018-02-20 14:05:36 -0500168 }
Jim Van Verth52fb02e2017-06-27 10:36:56 -0400169 }
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400170}
171
172DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TransferPixelsTest, reporter, ctxInfo) {
173 // RGBA
Brian Salomona6948702018-06-01 15:33:20 -0400174 basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kRGBA_8888, false);
175 basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kRGBA_8888, true);
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400176
177 // BGRA
Brian Salomona6948702018-06-01 15:33:20 -0400178 basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kBGRA_8888, false);
179 basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kBGRA_8888, true);
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400180}