1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 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/gpu/GrDirectContext.h" 9cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 10cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h" 11cb93a386Sopenharmony_ci#include "src/gpu/GrShaderCaps.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxyPriv.h" 14cb93a386Sopenharmony_ci#include "src/gpu/SurfaceFillContext.h" 15cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLGpu.h" 16cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLUtil.h" 17cb93a386Sopenharmony_ci#include "tests/Test.h" 18cb93a386Sopenharmony_ci#include "tests/TestUtils.h" 19cb93a386Sopenharmony_ci#include "tools/gpu/GrContextFactory.h" 20cb93a386Sopenharmony_ci#include "tools/gpu/ManagedBackendTexture.h" 21cb93a386Sopenharmony_ci#include "tools/gpu/gl/GLTestContext.h" 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ci#ifdef SK_GL 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ciusing sk_gpu_test::GLTestContext; 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_cistatic void cleanup(GLTestContext* glctx0, 28cb93a386Sopenharmony_ci GrGLuint texID0, 29cb93a386Sopenharmony_ci GLTestContext* glctx1, 30cb93a386Sopenharmony_ci sk_sp<GrDirectContext> dContext, 31cb93a386Sopenharmony_ci GrEGLImage image1) { 32cb93a386Sopenharmony_ci if (glctx1) { 33cb93a386Sopenharmony_ci glctx1->makeCurrent(); 34cb93a386Sopenharmony_ci if (GR_EGL_NO_IMAGE != image1) { 35cb93a386Sopenharmony_ci glctx1->destroyEGLImage(image1); 36cb93a386Sopenharmony_ci } 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci glctx0->makeCurrent(); 40cb93a386Sopenharmony_ci if (texID0) { 41cb93a386Sopenharmony_ci GR_GL_CALL(glctx0->gl(), DeleteTextures(1, &texID0)); 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(EGLImageTest, reporter, ctxInfo) { 46cb93a386Sopenharmony_ci auto context0 = ctxInfo.directContext(); 47cb93a386Sopenharmony_ci sk_gpu_test::GLTestContext* glCtx0 = ctxInfo.glContext(); 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci // Try to create a second GL context and then check if the contexts have necessary 50cb93a386Sopenharmony_ci // extensions to run this test. 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci if (kGLES_GrGLStandard != glCtx0->gl()->fStandard) { 53cb93a386Sopenharmony_ci return; 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci GrGLGpu* gpu0 = static_cast<GrGLGpu*>(context0->priv().getGpu()); 56cb93a386Sopenharmony_ci if (!gpu0->glCaps().shaderCaps()->externalTextureSupport()) { 57cb93a386Sopenharmony_ci return; 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci std::unique_ptr<GLTestContext> glCtx1 = glCtx0->makeNew(); 61cb93a386Sopenharmony_ci if (!glCtx1) { 62cb93a386Sopenharmony_ci return; 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci sk_sp<GrDirectContext> context1 = GrDirectContext::MakeGL(sk_ref_sp(glCtx1->gl())); 65cb93a386Sopenharmony_ci GrEGLImage image = GR_EGL_NO_IMAGE; 66cb93a386Sopenharmony_ci GrGLTextureInfo externalTexture; 67cb93a386Sopenharmony_ci externalTexture.fID = 0; 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ci if (!context1) { 70cb93a386Sopenharmony_ci cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image); 71cb93a386Sopenharmony_ci return; 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci if (!glCtx1->gl()->hasExtension("EGL_KHR_image") || 75cb93a386Sopenharmony_ci !glCtx1->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) { 76cb93a386Sopenharmony_ci cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image); 77cb93a386Sopenharmony_ci return; 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci ///////////////////////////////// CONTEXT 1 /////////////////////////////////// 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci // Use GL Context 1 to create a texture unknown to context 0. 83cb93a386Sopenharmony_ci context1->flushAndSubmit(); 84cb93a386Sopenharmony_ci static const int kSize = 100; 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData( 87cb93a386Sopenharmony_ci context1.get(), kSize, kSize, kRGBA_8888_SkColorType, GrMipmapped::kNo, 88cb93a386Sopenharmony_ci GrRenderable::kNo, GrProtected::kNo); 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci if (!mbet) { 91cb93a386Sopenharmony_ci ERRORF(reporter, "Error creating texture for EGL Image"); 92cb93a386Sopenharmony_ci cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image); 93cb93a386Sopenharmony_ci return; 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci GrGLTextureInfo texInfo; 97cb93a386Sopenharmony_ci if (!mbet->texture().getGLTextureInfo(&texInfo)) { 98cb93a386Sopenharmony_ci ERRORF(reporter, "Failed to get GrGLTextureInfo"); 99cb93a386Sopenharmony_ci return; 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ci if (GR_GL_TEXTURE_2D != texInfo.fTarget) { 103cb93a386Sopenharmony_ci ERRORF(reporter, "Expected backend texture to be 2D"); 104cb93a386Sopenharmony_ci cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image); 105cb93a386Sopenharmony_ci return; 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci // Wrap the texture in an EGLImage 109cb93a386Sopenharmony_ci image = glCtx1->texture2DToEGLImage(texInfo.fID); 110cb93a386Sopenharmony_ci if (GR_EGL_NO_IMAGE == image) { 111cb93a386Sopenharmony_ci ERRORF(reporter, "Error creating EGL Image from texture"); 112cb93a386Sopenharmony_ci cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image); 113cb93a386Sopenharmony_ci return; 114cb93a386Sopenharmony_ci } 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci // Since we are dealing with two different GL contexts here, we need to call finish so that the 117cb93a386Sopenharmony_ci // clearing of the texture that happens in createTextingOnlyBackendTexture occurs before we call 118cb93a386Sopenharmony_ci // TexSubImage below on the other context. Otherwise, it is possible the calls get reordered and 119cb93a386Sopenharmony_ci // the clearing overwrites the TexSubImage writes. 120cb93a386Sopenharmony_ci GR_GL_CALL(glCtx1->gl(), Finish()); 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci // Populate the texture using GL context 1. Important to use TexSubImage as TexImage orphans 123cb93a386Sopenharmony_ci // the EGL image. Also, this must be done after creating the EGLImage as the texture 124cb93a386Sopenharmony_ci // contents may not be preserved when the image is created. 125cb93a386Sopenharmony_ci SkAutoTMalloc<uint32_t> pixels(kSize * kSize); 126cb93a386Sopenharmony_ci for (int i = 0; i < kSize*kSize; ++i) { 127cb93a386Sopenharmony_ci pixels.get()[i] = 0xDDAABBCC; 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci GR_GL_CALL(glCtx1->gl(), ActiveTexture(GR_GL_TEXTURE0)); 130cb93a386Sopenharmony_ci GR_GL_CALL(glCtx1->gl(), BindTexture(texInfo.fTarget, texInfo.fID)); 131cb93a386Sopenharmony_ci GR_GL_CALL(glCtx1->gl(), TexSubImage2D(texInfo.fTarget, 0, 0, 0, kSize, kSize, 132cb93a386Sopenharmony_ci GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, pixels.get())); 133cb93a386Sopenharmony_ci GR_GL_CALL(glCtx1->gl(), Finish()); 134cb93a386Sopenharmony_ci // We've been making direct GL calls in GL context 1, let GrDirectContext 1 know its internal 135cb93a386Sopenharmony_ci // state is invalid. 136cb93a386Sopenharmony_ci context1->resetContext(); 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci ///////////////////////////////// CONTEXT 0 /////////////////////////////////// 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci // Make a new texture ID in GL Context 0 from the EGL Image 141cb93a386Sopenharmony_ci glCtx0->makeCurrent(); 142cb93a386Sopenharmony_ci externalTexture.fTarget = GR_GL_TEXTURE_EXTERNAL; 143cb93a386Sopenharmony_ci externalTexture.fID = glCtx0->eglImageToExternalTexture(image); 144cb93a386Sopenharmony_ci externalTexture.fFormat = GR_GL_RGBA8; 145cb93a386Sopenharmony_ci if (0 == externalTexture.fID) { 146cb93a386Sopenharmony_ci ERRORF(reporter, "Error converting EGL Image back to texture"); 147cb93a386Sopenharmony_ci cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image); 148cb93a386Sopenharmony_ci return; 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci // Wrap this texture ID in a GrTexture 152cb93a386Sopenharmony_ci GrBackendTexture backendTex(kSize, kSize, GrMipmapped::kNo, externalTexture); 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_ci GrColorInfo colorInfo(GrColorType::kRGBA_8888, kPremul_SkAlphaType, nullptr); 155cb93a386Sopenharmony_ci // TODO: If I make this TopLeft origin to match resolve_origin calls for kDefault, this test 156cb93a386Sopenharmony_ci // fails on the Nexus5. Why? 157cb93a386Sopenharmony_ci GrSurfaceOrigin origin = kBottomLeft_GrSurfaceOrigin; 158cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> texProxy = context0->priv().proxyProvider()->wrapBackendTexture( 159cb93a386Sopenharmony_ci backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType); 160cb93a386Sopenharmony_ci if (!texProxy) { 161cb93a386Sopenharmony_ci ERRORF(reporter, "Error wrapping external texture in GrTextureProxy."); 162cb93a386Sopenharmony_ci cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image); 163cb93a386Sopenharmony_ci return; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci GrSwizzle swizzle = context0->priv().caps()->getReadSwizzle(texProxy->backendFormat(), 166cb93a386Sopenharmony_ci colorInfo.colorType()); 167cb93a386Sopenharmony_ci GrSurfaceProxyView view(std::move(texProxy), origin, swizzle); 168cb93a386Sopenharmony_ci auto surfaceContext = context0->priv().makeSC(std::move(view), colorInfo); 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci if (!surfaceContext) { 171cb93a386Sopenharmony_ci ERRORF(reporter, "Error wrapping external texture in SurfaceContext."); 172cb93a386Sopenharmony_ci cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image); 173cb93a386Sopenharmony_ci return; 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci GrTextureProxy* proxy = surfaceContext->asTextureProxy(); 177cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy->mipmapped() == GrMipmapped::kNo); 178cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy->peekTexture()->mipmapped() == GrMipmapped::kNo); 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy->textureType() == GrTextureType::kExternal); 181cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy->peekTexture()->textureType() == GrTextureType::kExternal); 182cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy->hasRestrictedSampling()); 183cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy->peekTexture()->hasRestrictedSampling()); 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci // Should not be able to wrap as a RT 186cb93a386Sopenharmony_ci { 187cb93a386Sopenharmony_ci auto temp = context0->priv().makeSFCFromBackendTexture(colorInfo, 188cb93a386Sopenharmony_ci backendTex, 189cb93a386Sopenharmony_ci 1, 190cb93a386Sopenharmony_ci origin, 191cb93a386Sopenharmony_ci /*release helper*/ nullptr); 192cb93a386Sopenharmony_ci if (temp) { 193cb93a386Sopenharmony_ci ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture as a RT."); 194cb93a386Sopenharmony_ci } 195cb93a386Sopenharmony_ci } 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_ci //TestReadPixels(reporter, context0, surfaceContext.get(), pixels.get(), "EGLImageTest-read"); 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci SkDebugf("type: %d\n", (int)surfaceContext->asTextureProxy()->textureType()); 200cb93a386Sopenharmony_ci // We should not be able to write to an EXTERNAL texture 201cb93a386Sopenharmony_ci TestWritePixels(reporter, context0, surfaceContext.get(), false, "EGLImageTest-write"); 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_ci // Only test RT-config 204cb93a386Sopenharmony_ci // TODO: why do we always need to draw to copy from an external texture? 205cb93a386Sopenharmony_ci TestCopyFromSurface(reporter, 206cb93a386Sopenharmony_ci context0, 207cb93a386Sopenharmony_ci surfaceContext->asSurfaceProxyRef(), 208cb93a386Sopenharmony_ci surfaceContext->origin(), 209cb93a386Sopenharmony_ci colorInfo.colorType(), 210cb93a386Sopenharmony_ci pixels.get(), 211cb93a386Sopenharmony_ci "EGLImageTest-copy"); 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_ci cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image); 214cb93a386Sopenharmony_ci} 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci#endif // SK_GL 217