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