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