• 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 "include/core/SkSurface.h"
9 #include "include/gpu/GrDirectContext.h"
10 #include "src/gpu/GrDirectContextPriv.h"
11 #include "src/gpu/gl/GrGLDefines.h"
12 #include "src/gpu/gl/GrGLGpu.h"
13 #include "src/gpu/gl/GrGLUtil.h"
14 #include "tests/Test.h"
15 
16 #ifdef SK_GL
17 
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(TextureBindingsResetTest,reporter,ctxInfo)18 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(TextureBindingsResetTest, reporter, ctxInfo) {
19 #define GL(F) GR_GL_CALL(ctxInfo.glContext()->gl(), F)
20 
21     auto dContext = ctxInfo.directContext();
22     GrGpu* gpu = dContext->priv().getGpu();
23     GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());
24 
25     struct Target {
26         GrGLenum fName;
27         GrGLenum fQuery;
28     };
29     SkTDArray<Target> targets;
30     targets.push_back({GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BINDING_2D});
31     bool supportExternal;
32     if ((supportExternal = glGpu->glCaps().shaderCaps()->externalTextureSupport())) {
33         targets.push_back({GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_BINDING_EXTERNAL});
34     }
35     bool supportRectangle;
36     if ((supportRectangle = glGpu->glCaps().rectangleTextureSupport())) {
37         targets.push_back({GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_BINDING_RECTANGLE});
38     }
39     GrGLint numUnits = 0;
40     GL(GetIntegerv(GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numUnits));
41     SkTDArray<GrGLuint> claimedIDs;
42     claimedIDs.setCount(numUnits * targets.count());
43     GL(GenTextures(claimedIDs.count(), claimedIDs.begin()));
44 
45     auto resetBindings = [&] {
46         int i = 0;
47         for (int u = 0; u < numUnits; ++u) {
48             GL(ActiveTexture(GR_GL_TEXTURE0 + u));
49             for (auto target : targets) {
50                 GL(BindTexture(target.fName, claimedIDs[i++]));
51             }
52         }
53     };
54     auto checkBindings = [&] {
55         int i = 0;
56         for (int u = 0; u < numUnits; ++u) {
57             GL(ActiveTexture(GR_GL_TEXTURE0 + u));
58             for (auto target : targets) {
59                 GrGLint boundID = -1;
60                 GL(GetIntegerv(target.fQuery, &boundID));
61                 if (boundID != (int) claimedIDs[i] && boundID != 0) {
62                     ERRORF(reporter, "Unit %d, target 0x%04x has ID %d bound. Expected %d or 0.", u,
63                            target.fName, boundID, claimedIDs[i]);
64                     return;
65                 }
66                 ++i;
67             }
68         }
69     };
70 
71     // Initialize texture unit/target combo bindings to 0.
72     dContext->flushAndSubmit();
73     resetBindings();
74     dContext->resetContext();
75 
76     // Test creating a texture and then resetting bindings.
77     static constexpr SkISize kDims = {10, 10};
78     GrBackendFormat format = gpu->caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
79                                                                   GrRenderable::kNo);
80     auto tex = gpu->createTexture(kDims, format, GrTextureType::k2D, GrRenderable::kNo, 1,
81                                   GrMipmapped::kNo, SkBudgeted::kNo, GrProtected::kNo);
82     REPORTER_ASSERT(reporter, tex);
83     dContext->resetGLTextureBindings();
84     checkBindings();
85     resetBindings();
86     dContext->resetContext();
87 
88     // Test drawing and then resetting bindings. This should force a MIP regeneration if MIP
89     // maps are supported as well.
90     auto info = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
91     auto surf = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kYes, info, 1, nullptr);
92     surf->getCanvas()->clear(0x80FF0000);
93     auto img = surf->makeImageSnapshot();
94     surf->getCanvas()->clear(SK_ColorBLUE);
95     surf->getCanvas()->save();
96     surf->getCanvas()->scale(0.25, 0.25);
97     surf->getCanvas()->drawImage(img.get(), 0, 0, SkSamplingOptions({1.0f/3, 1.0f/3}), nullptr);
98     surf->getCanvas()->restore();
99     surf->flushAndSubmit();
100     dContext->resetGLTextureBindings();
101     checkBindings();
102     resetBindings();
103     dContext->resetContext();
104 
105     if (supportExternal) {
106         GrBackendTexture texture2D = dContext->createBackendTexture(
107                 10, 10, kRGBA_8888_SkColorType,
108                 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo);
109         GrGLTextureInfo info2D;
110         REPORTER_ASSERT(reporter, texture2D.getGLTextureInfo(&info2D));
111         GrEGLImage eglImage = ctxInfo.glContext()->texture2DToEGLImage(info2D.fID);
112         REPORTER_ASSERT(reporter, eglImage);
113         GrGLTextureInfo infoExternal;
114         infoExternal.fID = ctxInfo.glContext()->eglImageToExternalTexture(eglImage);
115         infoExternal.fTarget = GR_GL_TEXTURE_EXTERNAL;
116         infoExternal.fFormat = info2D.fFormat;
117         REPORTER_ASSERT(reporter, infoExternal.fID);
118         GrBackendTexture backendTexture(10, 10, GrMipmapped::kNo, infoExternal);
119         // Above texture creation will have messed with GL state and bindings.
120         resetBindings();
121         dContext->resetContext();
122         img = SkImage::MakeFromTexture(dContext, backendTexture, kTopLeft_GrSurfaceOrigin,
123                                        kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
124         REPORTER_ASSERT(reporter, img);
125         surf->getCanvas()->drawImage(img, 0, 0);
126         img.reset();
127         surf->flushAndSubmit();
128         dContext->resetGLTextureBindings();
129         checkBindings();
130         resetBindings();
131         GL(DeleteTextures(1, &infoExternal.fID));
132         ctxInfo.glContext()->destroyEGLImage(eglImage);
133         dContext->deleteBackendTexture(texture2D);
134         dContext->resetContext();
135     }
136 
137     if (supportRectangle) {
138         format = GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_RECTANGLE);
139         GrBackendTexture rectangleTexture =
140                 dContext->createBackendTexture(10, 10, format, GrMipmapped::kNo, GrRenderable::kNo);
141         if (rectangleTexture.isValid()) {
142             img = SkImage::MakeFromTexture(dContext, rectangleTexture, kTopLeft_GrSurfaceOrigin,
143                                            kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
144             REPORTER_ASSERT(reporter, img);
145             surf->getCanvas()->drawImage(img, 0, 0);
146             img.reset();
147             surf->flushAndSubmit();
148             dContext->resetGLTextureBindings();
149             checkBindings();
150             resetBindings();
151             dContext->deleteBackendTexture(rectangleTexture);
152         }
153     }
154 
155     GL(DeleteTextures(claimedIDs.count(), claimedIDs.begin()));
156 
157 #undef GL
158 }
159 
160 #endif  // SK_GL
161