blob: ff9d76d044335d38e35dfa1cdc18bb6550708953 [file] [log] [blame]
Greg Daniel177e6952017-10-12 12:27:11 -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#include "SkTypes.h"
9
10#if SK_SUPPORT_GPU
11
12#include "GrBackendSurface.h"
Greg Daniel261b8aa2017-10-23 09:37:36 -040013#include "GrBackendTextureImageGenerator.h"
Greg Daniel177e6952017-10-12 12:27:11 -040014#include "GrContext.h"
15#include "GrContextPriv.h"
16#include "GrGpu.h"
17#include "GrRenderTargetContext.h"
Greg Daniel261b8aa2017-10-23 09:37:36 -040018#include "GrSemaphore.h"
Greg Daniel177e6952017-10-12 12:27:11 -040019#include "GrSurfaceProxyPriv.h"
20#include "GrTest.h"
21#include "GrTexturePriv.h"
22#include "GrTextureProxy.h"
23#include "SkCanvas.h"
24#include "SkImage_Base.h"
25#include "SkGpuDevice.h"
Greg Daniel261b8aa2017-10-23 09:37:36 -040026#include "SkPoint.h"
Greg Daniel177e6952017-10-12 12:27:11 -040027#include "SkSurface.h"
28#include "SkSurface_Gpu.h"
29#include "Test.h"
30
Greg Daniel45d63032017-10-30 13:41:26 -040031static constexpr int kSize = 8;
32
Greg Daniel177e6952017-10-12 12:27:11 -040033// Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
34// SkImages and SkSurfaces
35DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
36 GrContext* context = ctxInfo.grContext();
Greg Daniel261b8aa2017-10-23 09:37:36 -040037 if (!context->caps()->mipMapSupport()) {
38 return;
39 }
Greg Daniel177e6952017-10-12 12:27:11 -040040 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
41 for (auto isRT : {false, true}) {
42 // CreateTestingOnlyBackendTexture currently doesn't support uploading data to mip maps
43 // so we don't send any. However, we pretend there is data for the checks below which is
44 // fine since we are never actually using these textures for any work on the gpu.
45 GrBackendObject backendHandle = context->getGpu()->createTestingOnlyBackendTexture(
Robert Phillips57e08282017-11-16 14:59:48 -050046 nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, isRT, mipMapped);
Greg Daniel177e6952017-10-12 12:27:11 -040047
48 GrBackend backend = context->contextPriv().getBackend();
49 GrBackendTexture backendTex = GrTest::CreateBackendTexture(backend,
Greg Daniel45d63032017-10-30 13:41:26 -040050 kSize,
51 kSize,
Greg Daniel177e6952017-10-12 12:27:11 -040052 kRGBA_8888_GrPixelConfig,
53 mipMapped,
54 backendHandle);
55
Robert Phillipse0070c02017-11-13 12:47:24 -050056 sk_sp<GrTextureProxy> proxy;
Greg Daniel177e6952017-10-12 12:27:11 -040057 sk_sp<SkImage> image;
58 if (isRT) {
59 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
60 context,
61 backendTex,
62 kTopLeft_GrSurfaceOrigin,
63 0,
64 nullptr,
65 nullptr);
66
67 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
Robert Phillipse0070c02017-11-13 12:47:24 -050068 proxy = device->accessRenderTargetContext()->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040069 } else {
70 image = SkImage::MakeFromTexture(context, backendTex,
71 kTopLeft_GrSurfaceOrigin,
72 kPremul_SkAlphaType, nullptr);
Robert Phillipse0070c02017-11-13 12:47:24 -050073 proxy = as_IB(image)->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040074 }
75 REPORTER_ASSERT(reporter, proxy);
76 if (!proxy) {
77 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
78 return;
79 }
80
81 REPORTER_ASSERT(reporter, proxy->priv().isInstantiated());
82
83 GrTexture* texture = proxy->priv().peekTexture();
84 REPORTER_ASSERT(reporter, texture);
85 if (!texture) {
86 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
87 return;
88 }
89
90 if (GrMipMapped::kYes == mipMapped) {
Greg Daniele252f082017-10-23 16:05:23 -040091 REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
Greg Daniel177e6952017-10-12 12:27:11 -040092 if (isRT) {
93 REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
94 } else {
95 REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
96 }
97 } else {
Greg Daniele252f082017-10-23 16:05:23 -040098 REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
Greg Daniel177e6952017-10-12 12:27:11 -040099 }
100 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
101 }
102 }
103}
104
Greg Daniel261b8aa2017-10-23 09:37:36 -0400105// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
106// based on if we will use mips in the draw and the mip status of the GrBackendTexture.
107DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400108 GrContext* context = ctxInfo.grContext();
109 if (!context->caps()->mipMapSupport()) {
110 return;
111 }
112 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
113 for (auto willUseMips : {false, true}) {
114 GrBackendObject backendHandle = context->getGpu()->createTestingOnlyBackendTexture(
115 nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, false, mipMapped);
116
117 GrBackend backend = context->contextPriv().getBackend();
118 GrBackendTexture backendTex = GrTest::CreateBackendTexture(backend,
119 kSize,
120 kSize,
121 kRGBA_8888_GrPixelConfig,
122 mipMapped,
123 backendHandle);
124
125 sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
126 kTopLeft_GrSurfaceOrigin,
127 kPremul_SkAlphaType, nullptr);
128
129 GrTextureProxy* proxy = as_IB(image)->peekProxy();
130 REPORTER_ASSERT(reporter, proxy);
131 if (!proxy) {
132 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
133 return;
134 }
135
136 REPORTER_ASSERT(reporter, proxy->priv().isInstantiated());
137
138 sk_sp<GrTexture> texture = sk_ref_sp(proxy->priv().peekTexture());
139 REPORTER_ASSERT(reporter, texture);
140 if (!texture) {
141 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
142 return;
143 }
144
145 std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
146 texture, kTopLeft_GrSurfaceOrigin, nullptr, kPremul_SkAlphaType, nullptr);
147 REPORTER_ASSERT(reporter, imageGen);
148 if (!imageGen) {
149 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
150 return;
151 }
152
153 SkIPoint origin = SkIPoint::Make(0,0);
154 // The transfer function behavior isn't used in the generator so set we set it
155 // arbitrarily here.
156 SkTransferFunctionBehavior behavior = SkTransferFunctionBehavior::kIgnore;
157 SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
158 kPremul_SkAlphaType);
159 sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
160 origin, behavior,
161 willUseMips);
162
163 REPORTER_ASSERT(reporter, genProxy);
164 if (!genProxy) {
165 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
166 return;
167 }
168
169 REPORTER_ASSERT(reporter, genProxy->priv().isInstantiated());
170
171 GrTexture* genTexture = genProxy->priv().peekTexture();
172 REPORTER_ASSERT(reporter, genTexture);
173 if (!genTexture) {
174 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
175 return;
176 }
177
178 GrBackendObject genBackendObject = genTexture->getTextureHandle();
179
180 if (kOpenGL_GrBackend == backend) {
181 const GrGLTextureInfo* origTexInfo = backendTex.getGLTextureInfo();
182 GrGLTextureInfo* genTexInfo = (GrGLTextureInfo*)genBackendObject;
183 if (willUseMips && GrMipMapped::kNo == mipMapped) {
184 // We did a copy so the texture IDs should be different
185 REPORTER_ASSERT(reporter, origTexInfo->fID != genTexInfo->fID);
186 } else {
187 REPORTER_ASSERT(reporter, origTexInfo->fID == genTexInfo->fID);
188 }
189 } else if (kVulkan_GrBackend == backend) {
190#ifdef SK_VULKAN
191 const GrVkImageInfo* origImageInfo = backendTex.getVkImageInfo();
192 GrVkImageInfo* genImageInfo = (GrVkImageInfo*)genBackendObject;
193 if (willUseMips && GrMipMapped::kNo == mipMapped) {
194 // We did a copy so the texture IDs should be different
195 REPORTER_ASSERT(reporter, origImageInfo->fImage != genImageInfo->fImage);
196 } else {
197 REPORTER_ASSERT(reporter, origImageInfo->fImage == genImageInfo->fImage);
198 }
199#endif
200 } else if (kMetal_GrBackend == backend) {
201 REPORTER_ASSERT(reporter, false);
202 } else {
203 REPORTER_ASSERT(reporter, false);
204 }
205
206 // Must make sure the uses of the backend texture have finished (we possibly have a
207 // queued up copy) before we delete the backend texture. Thus we use readPixels here
208 // just to force the synchronization.
209 sk_sp<GrSurfaceContext> surfContext =
210 context->contextPriv().makeWrappedSurfaceContext(genProxy, nullptr);
211
212 SkBitmap bitmap;
213 bitmap.allocPixels(imageInfo);
214 surfContext->readPixels(imageInfo, bitmap.getPixels(), 0, 0, 0, 0);
215
216 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
217 }
218 }
219}
220
Greg Daniel45d63032017-10-30 13:41:26 -0400221// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
222// resource we took the snapshot of.
223DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
224 GrContext* context = ctxInfo.grContext();
225 if (!context->caps()->mipMapSupport()) {
226 return;
227 }
228
229 for (auto willUseMips : {false, true}) {
230 for (auto isWrapped : {false, true}) {
231 GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
232 sk_sp<SkSurface> surface;
233 GrBackendObject backendHandle = context->getGpu()->createTestingOnlyBackendTexture(
234 nullptr, 8, 8, kRGBA_8888_GrPixelConfig, true, mipMapped);
235 if (isWrapped) {
236 GrBackend backend = context->contextPriv().getBackend();
237 GrBackendTexture backendTex = GrTest::CreateBackendTexture(backend,
238 kSize,
239 kSize,
240 kRGBA_8888_GrPixelConfig,
241 mipMapped,
242 backendHandle);
243
244 surface = SkSurface::MakeFromBackendTexture(context,
245 backendTex,
246 kTopLeft_GrSurfaceOrigin,
247 0,
248 nullptr,
249 nullptr);
250 } else {
251 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
252 kPremul_SkAlphaType);
253 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
254 kTopLeft_GrSurfaceOrigin, nullptr,
255 willUseMips);
256 }
257 REPORTER_ASSERT(reporter, surface);
258 if (!surface) {
259 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
260 }
261 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
262 GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
263 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
264
265 texProxy->instantiate(context->resourceProvider());
266 GrTexture* texture = texProxy->priv().peekTexture();
267 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
268
269 sk_sp<SkImage> image = surface->makeImageSnapshot();
270 REPORTER_ASSERT(reporter, image);
271 if (!image) {
272 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
273 }
274 texProxy = as_IB(image)->peekProxy();
275 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
276
277 texProxy->instantiate(context->resourceProvider());
278 texture = texProxy->priv().peekTexture();
279 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
280
281 // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
282 // to the gpu before we delete the backendHandle.
283 context->flush();
284 context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
285 }
286 }
287}
Greg Daniel261b8aa2017-10-23 09:37:36 -0400288
Greg Daniel177e6952017-10-12 12:27:11 -0400289#endif