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