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