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