EGLImageTest.cpp revision d17f6584df9e48146dac28a1df56fb4978de6ba3
1/* 2 * Copyright 2015 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 "Test.h" 9#include "TestUtils.h" 10#if SK_SUPPORT_GPU 11#include "GrContext.h" 12#include "GrContextFactory.h" 13#include "GrContextPriv.h" 14#include "GrRenderTargetContext.h" 15#include "GrShaderCaps.h" 16#include "GrTest.h" 17#include "GrTextureContext.h" 18#include "gl/GLTestContext.h" 19#include "gl/GrGLGpu.h" 20#include "gl/GrGLUtil.h" 21 22using sk_gpu_test::GLTestContext; 23 24static void cleanup(GLTestContext* glctx0, GrGLuint texID0, GLTestContext* glctx1, GrContext* grctx1, 25 const GrGLTextureInfo* grbackendtex1, GrEGLImage image1) { 26 if (glctx1) { 27 glctx1->makeCurrent(); 28 if (grctx1) { 29 if (grbackendtex1) { 30 GrGLGpu* gpu1 = static_cast<GrGLGpu*>(grctx1->getGpu()); 31 GrBackendObject handle = reinterpret_cast<GrBackendObject>(grbackendtex1); 32 gpu1->deleteTestingOnlyBackendTexture(handle, false); 33 } 34 grctx1->unref(); 35 } 36 if (GR_EGL_NO_IMAGE != image1) { 37 glctx1->destroyEGLImage(image1); 38 } 39 } 40 41 glctx0->makeCurrent(); 42 if (texID0) { 43 GR_GL_CALL(glctx0->gl(), DeleteTextures(1, &texID0)); 44 } 45} 46 47DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(EGLImageTest, reporter, ctxInfo) { 48 GrContext* context0 = ctxInfo.grContext(); 49 sk_gpu_test::GLTestContext* glCtx0 = ctxInfo.glContext(); 50 51 // Try to create a second GL context and then check if the contexts have necessary 52 // extensions to run this test. 53 54 if (kGLES_GrGLStandard != glCtx0->gl()->fStandard) { 55 return; 56 } 57 GrGLGpu* gpu0 = static_cast<GrGLGpu*>(context0->getGpu()); 58 if (!gpu0->glCaps().shaderCaps()->externalTextureSupport()) { 59 return; 60 } 61 62 std::unique_ptr<GLTestContext> glCtx1 = glCtx0->makeNew(); 63 if (!glCtx1) { 64 return; 65 } 66 GrContext* context1 = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)glCtx1->gl()); 67 const GrGLTextureInfo* backendTexture1 = nullptr; 68 GrEGLImage image = GR_EGL_NO_IMAGE; 69 GrGLTextureInfo externalTexture; 70 externalTexture.fID = 0; 71 72 if (!context1) { 73 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image); 74 return; 75 } 76 77 if (!glCtx1->gl()->hasExtension("EGL_KHR_image") || 78 !glCtx1->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) { 79 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image); 80 return; 81 } 82 83 ///////////////////////////////// CONTEXT 1 /////////////////////////////////// 84 85 // Use GL Context 1 to create a texture unknown to GrContext. 86 context1->flush(); 87 GrGpu* gpu1 = context1->getGpu(); 88 static const int kSize = 100; 89 backendTexture1 = reinterpret_cast<const GrGLTextureInfo*>( 90 gpu1->createTestingOnlyBackendTexture(nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig)); 91 if (!backendTexture1 || !backendTexture1->fID) { 92 ERRORF(reporter, "Error creating texture for EGL Image"); 93 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image); 94 return; 95 } 96 if (GR_GL_TEXTURE_2D != backendTexture1->fTarget) { 97 ERRORF(reporter, "Expected backend texture to be 2D"); 98 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image); 99 return; 100 } 101 102 // Wrap the texture in an EGLImage 103 image = glCtx1->texture2DToEGLImage(backendTexture1->fID); 104 if (GR_EGL_NO_IMAGE == image) { 105 ERRORF(reporter, "Error creating EGL Image from texture"); 106 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image); 107 return; 108 } 109 110 // Populate the texture using GL context 1. Important to use TexSubImage as TexImage orphans 111 // the EGL image. Also, this must be done after creating the EGLImage as the texture 112 // contents may not be preserved when the image is created. 113 SkAutoTMalloc<uint32_t> pixels(kSize * kSize); 114 for (int i = 0; i < kSize*kSize; ++i) { 115 pixels.get()[i] = 0xDDAABBCC; 116 } 117 GR_GL_CALL(glCtx1->gl(), ActiveTexture(GR_GL_TEXTURE0)); 118 GR_GL_CALL(glCtx1->gl(), BindTexture(backendTexture1->fTarget, backendTexture1->fID)); 119 GR_GL_CALL(glCtx1->gl(), TexSubImage2D(backendTexture1->fTarget, 0, 0, 0, kSize, kSize, 120 GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, pixels.get())); 121 GR_GL_CALL(glCtx1->gl(), Finish()); 122 // We've been making direct GL calls in GL context 1, let GrContext 1 know its internal 123 // state is invalid. 124 context1->resetContext(); 125 126 ///////////////////////////////// CONTEXT 0 /////////////////////////////////// 127 128 // Make a new texture ID in GL Context 0 from the EGL Image 129 glCtx0->makeCurrent(); 130 externalTexture.fTarget = GR_GL_TEXTURE_EXTERNAL; 131 externalTexture.fID = glCtx0->eglImageToExternalTexture(image); 132 if (0 == externalTexture.fID) { 133 ERRORF(reporter, "Error converting EGL Image back to texture"); 134 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image); 135 return; 136 } 137 138 // Wrap this texture ID in a GrTexture 139 GrBackendTexture backendTex(kSize, kSize, kRGBA_8888_GrPixelConfig, externalTexture); 140 141 // TODO: If I make this TopLeft origin to match resolve_origin calls for kDefault, this test 142 // fails on the Nexus5. Why? 143 sk_sp<GrTextureContext> surfaceContext = context0->contextPriv().makeBackendTextureContext( 144 backendTex, kBottomLeft_GrSurfaceOrigin, nullptr); 145 146 if (!surfaceContext) { 147 ERRORF(reporter, "Error wrapping external texture in GrSurfaceContext."); 148 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image); 149 return; 150 } 151 152 // Should not be able to wrap as a RT 153 { 154 sk_sp<GrRenderTargetContext> temp = 155 context0->contextPriv().makeBackendTextureRenderTargetContext( 156 backendTex, kBottomLeft_GrSurfaceOrigin, 0, nullptr); 157 if (temp) { 158 ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture as a RT."); 159 } 160 } 161 162 test_read_pixels(reporter, surfaceContext.get(), pixels.get(), "EGLImageTest-read"); 163 164 // We should not be able to write to a EXTERNAL texture 165 test_write_pixels(reporter, surfaceContext.get(), false, "EGLImageTest-write"); 166 167 // Only test RT-config 168 // TODO: why do we always need to draw to copy from an external texture? 169 test_copy_from_surface(reporter, context0, surfaceContext->asSurfaceProxy(), 170 pixels.get(), true, "EGLImageTest-copy"); 171 172 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image); 173} 174 175#endif 176