xref: /aosp_15_r20/external/skia/tests/TextureBindingsResetTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2019 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 "tests/Test.h"
9 
10 #ifdef SK_GL
11 #include "include/core/SkAlphaType.h"
12 #include "include/core/SkCanvas.h"
13 #include "include/core/SkColor.h"
14 #include "include/core/SkColorSpace.h"
15 #include "include/core/SkColorType.h"
16 #include "include/core/SkImage.h"
17 #include "include/core/SkImageInfo.h"
18 #include "include/core/SkRefCnt.h"
19 #include "include/core/SkSamplingOptions.h"
20 #include "include/core/SkSize.h"
21 #include "include/core/SkSurface.h"
22 #include "include/core/SkTypes.h"
23 #include "include/gpu/GpuTypes.h"
24 #include "include/gpu/ganesh/GrBackendSurface.h"
25 #include "include/gpu/ganesh/GrDirectContext.h"
26 #include "include/gpu/ganesh/GrTypes.h"
27 #include "include/gpu/ganesh/SkImageGanesh.h"
28 #include "include/gpu/ganesh/SkSurfaceGanesh.h"
29 #include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
30 #include "include/gpu/ganesh/gl/GrGLFunctions.h"
31 #include "include/gpu/ganesh/gl/GrGLInterface.h"
32 #include "include/gpu/ganesh/gl/GrGLTypes.h"
33 #include "include/private/base/SkTDArray.h"
34 #include "include/private/gpu/ganesh/GrTypesPriv.h"
35 #include "src/gpu/ganesh/GrCaps.h"
36 #include "src/gpu/ganesh/GrDirectContextPriv.h"
37 #include "src/gpu/ganesh/GrGpu.h"
38 #include "src/gpu/ganesh/GrShaderCaps.h"
39 #include "src/gpu/ganesh/gl/GrGLCaps.h"
40 #include "src/gpu/ganesh/gl/GrGLDefines.h"
41 #include "src/gpu/ganesh/gl/GrGLGpu.h"
42 #include "src/gpu/ganesh/gl/GrGLUtil.h"
43 #include "tests/CtsEnforcement.h"
44 #include "tools/gpu/gl/GLTestContext.h"
45 
46 struct GrContextOptions;
47 
DEF_GANESH_TEST_FOR_GL_CONTEXT(TextureBindingsResetTest,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)48 DEF_GANESH_TEST_FOR_GL_CONTEXT(TextureBindingsResetTest,
49                                reporter,
50                                ctxInfo,
51                                CtsEnforcement::kApiLevel_T) {
52 #define GL(F) GR_GL_CALL(ctxInfo.glContext()->gl(), F)
53 
54     auto dContext = ctxInfo.directContext();
55     GrGpu* gpu = dContext->priv().getGpu();
56     GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());
57 
58     struct Target {
59         GrGLenum fName;
60         GrGLenum fQuery;
61     };
62     SkTDArray<Target> targets;
63     targets.push_back({GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BINDING_2D});
64     bool supportExternal;
65     if ((supportExternal = glGpu->glCaps().shaderCaps()->fExternalTextureSupport)) {
66         targets.push_back({GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_BINDING_EXTERNAL});
67     }
68     bool supportRectangle;
69     if ((supportRectangle = glGpu->glCaps().rectangleTextureSupport())) {
70         targets.push_back({GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_BINDING_RECTANGLE});
71     }
72     GrGLint numUnits = 0;
73     GL(GetIntegerv(GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numUnits));
74     SkTDArray<GrGLuint> claimedIDs;
75     claimedIDs.resize(numUnits * targets.size());
76     GL(GenTextures(claimedIDs.size(), claimedIDs.begin()));
77 
78     auto resetBindings = [&] {
79         int i = 0;
80         for (int u = 0; u < numUnits; ++u) {
81             GL(ActiveTexture(GR_GL_TEXTURE0 + u));
82             for (auto target : targets) {
83                 GL(BindTexture(target.fName, claimedIDs[i++]));
84             }
85         }
86     };
87     auto checkBindings = [&] {
88         int i = 0;
89         for (int u = 0; u < numUnits; ++u) {
90             GL(ActiveTexture(GR_GL_TEXTURE0 + u));
91             for (auto target : targets) {
92                 GrGLint boundID = -1;
93                 GL(GetIntegerv(target.fQuery, &boundID));
94                 if (boundID != (int) claimedIDs[i] && boundID != 0) {
95                     ERRORF(reporter, "Unit %d, target 0x%04x has ID %d bound. Expected %u or 0.", u,
96                            target.fName, boundID, claimedIDs[i]);
97                     return;
98                 }
99                 ++i;
100             }
101         }
102     };
103 
104     // Initialize texture unit/target combo bindings to 0.
105     dContext->flushAndSubmit();
106     resetBindings();
107     dContext->resetContext();
108 
109     // Test creating a texture and then resetting bindings.
110     static constexpr SkISize kDims = {10, 10};
111     GrBackendFormat format = gpu->caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
112                                                                   GrRenderable::kNo);
113     auto tex = gpu->createTexture(kDims,
114                                   format,
115                                   GrTextureType::k2D,
116                                   GrRenderable::kNo,
117                                   1,
118                                   skgpu::Mipmapped::kNo,
119                                   skgpu::Budgeted::kNo,
120                                   GrProtected::kNo,
121                                   /*label=*/"TextureBindingsResetTest");
122     REPORTER_ASSERT(reporter, tex);
123     dContext->resetGLTextureBindings();
124     checkBindings();
125     resetBindings();
126     dContext->resetContext();
127 
128     // Test drawing and then resetting bindings. This should force a MIP regeneration if MIP
129     // maps are supported as well.
130     auto info = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
131     auto surf = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kYes, info, 1, nullptr);
132     surf->getCanvas()->clear(0x80FF0000);
133     auto img = surf->makeImageSnapshot();
134     surf->getCanvas()->clear(SK_ColorBLUE);
135     surf->getCanvas()->save();
136     surf->getCanvas()->scale(0.25, 0.25);
137     surf->getCanvas()->drawImage(img.get(), 0, 0, SkSamplingOptions({1.0f/3, 1.0f/3}), nullptr);
138     surf->getCanvas()->restore();
139     dContext->flushAndSubmit(surf.get(), GrSyncCpu::kNo);
140     dContext->resetGLTextureBindings();
141     checkBindings();
142     resetBindings();
143     dContext->resetContext();
144 
145     if (supportExternal) {
146         GrBackendTexture texture2D = dContext->createBackendTexture(10,
147                                                                     10,
148                                                                     kRGBA_8888_SkColorType,
149                                                                     SkColors::kTransparent,
150                                                                     skgpu::Mipmapped::kNo,
151                                                                     GrRenderable::kNo,
152                                                                     GrProtected::kNo);
153         GrGLTextureInfo info2D;
154         REPORTER_ASSERT(reporter, GrBackendTextures::GetGLTextureInfo(texture2D, &info2D));
155         GrEGLImage eglImage = ctxInfo.glContext()->texture2DToEGLImage(info2D.fID);
156         REPORTER_ASSERT(reporter, eglImage);
157         GrGLTextureInfo infoExternal;
158         infoExternal.fID = ctxInfo.glContext()->eglImageToExternalTexture(eglImage);
159         infoExternal.fTarget = GR_GL_TEXTURE_EXTERNAL;
160         infoExternal.fFormat = info2D.fFormat;
161         REPORTER_ASSERT(reporter, infoExternal.fID);
162         infoExternal.fProtected = info2D.fProtected;
163         GrBackendTexture backendTexture =
164                 GrBackendTextures::MakeGL(10, 10, skgpu::Mipmapped::kNo, infoExternal);
165         // Above texture creation will have messed with GL state and bindings.
166         resetBindings();
167         dContext->resetContext();
168         img = SkImages::BorrowTextureFrom(dContext,
169                                           backendTexture,
170                                           kTopLeft_GrSurfaceOrigin,
171                                           kRGBA_8888_SkColorType,
172                                           kPremul_SkAlphaType,
173                                           nullptr);
174         REPORTER_ASSERT(reporter, img);
175         surf->getCanvas()->drawImage(img, 0, 0);
176         img.reset();
177         dContext->flushAndSubmit(surf.get(), GrSyncCpu::kNo);
178         dContext->resetGLTextureBindings();
179         checkBindings();
180         resetBindings();
181         GL(DeleteTextures(1, &infoExternal.fID));
182         ctxInfo.glContext()->destroyEGLImage(eglImage);
183         dContext->deleteBackendTexture(texture2D);
184         dContext->resetContext();
185     }
186 
187     if (supportRectangle) {
188         format = GrBackendFormats::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_RECTANGLE);
189         GrBackendTexture rectangleTexture = dContext->createBackendTexture(
190                 10, 10, format, skgpu::Mipmapped::kNo, GrRenderable::kNo);
191         if (rectangleTexture.isValid()) {
192             img = SkImages::BorrowTextureFrom(dContext,
193                                               rectangleTexture,
194                                               kTopLeft_GrSurfaceOrigin,
195                                               kRGBA_8888_SkColorType,
196                                               kPremul_SkAlphaType,
197                                               nullptr);
198             REPORTER_ASSERT(reporter, img);
199             surf->getCanvas()->drawImage(img, 0, 0);
200             img.reset();
201             dContext->flushAndSubmit(surf.get(), GrSyncCpu::kNo);
202             dContext->resetGLTextureBindings();
203             checkBindings();
204             resetBindings();
205             dContext->deleteBackendTexture(rectangleTexture);
206         }
207     }
208 
209     GL(DeleteTextures(claimedIDs.size(), claimedIDs.begin()));
210 
211 #undef GL
212 }
213 
214 #endif  // SK_GL
215