• 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 "src/gpu/GrContextPriv.h"
10 #include "src/gpu/gl/GrGLDefines.h"
11 #include "src/gpu/gl/GrGLGpu.h"
12 #include "src/gpu/gl/GrGLUtil.h"
13 #include "tests/Test.h"
14 
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(TextureBindingsResetTest,reporter,ctxInfo)15 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(TextureBindingsResetTest, reporter, ctxInfo) {
16 #define GL(F) GR_GL_CALL(ctxInfo.glContext()->gl(), F)
17 
18     GrContext* context = ctxInfo.grContext();
19     GrGpu* gpu = context->priv().getGpu();
20     GrGLGpu* glGpu = static_cast<GrGLGpu*>(context->priv().getGpu());
21 
22     struct Target {
23         GrGLenum fName;
24         GrGLenum fQuery;
25     };
26     SkTDArray<Target> targets;
27     targets.push_back({GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BINDING_2D});
28     bool supportExternal;
29     if ((supportExternal = glGpu->glCaps().shaderCaps()->externalTextureSupport())) {
30         targets.push_back({GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_BINDING_EXTERNAL});
31     }
32     bool supportRectangle;
33     if ((supportRectangle = glGpu->glCaps().rectangleTextureSupport())) {
34         targets.push_back({GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_BINDING_RECTANGLE});
35     }
36     GrGLint numUnits;
37     GL(GetIntegerv(GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numUnits));
38     SkTDArray<GrGLuint> claimedIDs;
39     claimedIDs.setCount(numUnits * targets.count());
40     GL(GenTextures(claimedIDs.count(), claimedIDs.begin()));
41 
42     auto resetBindings = [&] {
43         int i = 0;
44         for (int u = 0; u < numUnits; ++u) {
45             GL(ActiveTexture(GR_GL_TEXTURE0 + u));
46             for (auto target : targets) {
47                 GL(BindTexture(target.fName, claimedIDs[i++]));
48             }
49         }
50     };
51     auto checkBindings = [&] {
52         int i = 0;
53         for (int u = 0; u < numUnits; ++u) {
54             GL(ActiveTexture(GR_GL_TEXTURE0 + u));
55             for (auto target : targets) {
56                 GrGLuint boundID = ~0;
57                 GL(GetIntegerv(target.fQuery, reinterpret_cast<GrGLint*>(&boundID)));
58                 if (boundID != claimedIDs[i] && boundID != 0) {
59                     ERRORF(reporter, "Unit %d, target 0x%04x has ID %d bound. Expected %d or 0.", u,
60                            target.fName, boundID, claimedIDs[i]);
61                     return;
62                 }
63                 ++i;
64             }
65         }
66     };
67 
68     // Initialize texture unit/target combo bindings to 0.
69     context->flush();
70     resetBindings();
71     context->resetContext();
72 
73     // Test creating a texture and then resetting bindings.
74     GrSurfaceDesc desc;
75     desc.fWidth = desc.fHeight = 10;
76     desc.fConfig = kRGBA_8888_GrPixelConfig;
77     auto format = gpu->caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888, GrRenderable::kNo);
78     auto tex = gpu->createTexture(desc, format, GrRenderable::kNo, 1, SkBudgeted::kNo,
79                                   GrProtected::kNo);
80     REPORTER_ASSERT(reporter, tex);
81     context->resetGLTextureBindings();
82     checkBindings();
83     resetBindings();
84     context->resetContext();
85 
86     // Test drawing and then resetting bindings. This should force a MIP regeneration if MIP
87     // maps are supported as well.
88     auto info = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
89     auto surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 1, nullptr);
90     surf->getCanvas()->clear(0x80FF0000);
91     auto img = surf->makeImageSnapshot();
92     surf->getCanvas()->clear(SK_ColorBLUE);
93     surf->getCanvas()->save();
94     surf->getCanvas()->scale(0.25, 0.25);
95     SkPaint paint;
96     paint.setFilterQuality(kHigh_SkFilterQuality);
97     surf->getCanvas()->drawImage(img, 0, 0, &paint);
98     surf->getCanvas()->restore();
99     surf->flush();
100     context->resetGLTextureBindings();
101     checkBindings();
102     resetBindings();
103     context->resetContext();
104 
105     if (supportExternal) {
106         GrBackendTexture texture2D = context->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         context->resetContext();
122         img = SkImage::MakeFromTexture(context, 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->flush();
128         context->resetGLTextureBindings();
129         checkBindings();
130         resetBindings();
131         GL(DeleteTextures(1, &infoExternal.fID));
132         ctxInfo.glContext()->destroyEGLImage(eglImage);
133         context->deleteBackendTexture(texture2D);
134         context->resetContext();
135     }
136 
137     if (supportRectangle) {
138         GrGLuint id = ctxInfo.glContext()->createTextureRectangle(10, 10, GR_GL_RGBA, GR_GL_RGBA,
139                                                                   GR_GL_UNSIGNED_BYTE, nullptr);
140         // Above texture creation will have messed with GL state and bindings.
141         resetBindings();
142         context->resetContext();
143         if (id) {
144             GrGLTextureInfo info;
145             info.fTarget = GR_GL_TEXTURE_RECTANGLE;
146             info.fFormat = GR_GL_RGBA8;
147             info.fID = id;
148             GrBackendTexture backendTexture(10, 10, GrMipMapped::kNo, info);
149             img = SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin,
150                                            kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
151             REPORTER_ASSERT(reporter, img);
152             surf->getCanvas()->drawImage(img, 0, 0);
153             img.reset();
154             surf->flush();
155             context->resetGLTextureBindings();
156             checkBindings();
157             resetBindings();
158             GL(DeleteTextures(1, &id));
159             context->resetContext();
160         }
161     }
162 
163     GL(DeleteTextures(claimedIDs.count(), claimedIDs.begin()));
164 
165 #undef GL
166 }
167