EGLImageTest.cpp revision bd500f09ce5b1ca464431d693f9ec5da60a59230
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#if SK_SUPPORT_GPU 10#include "GrContext.h" 11#include "GrContextFactory.h" 12#include "gl/GrGLGpu.h" 13#include "gl/GrGLUtil.h" 14#include "gl/SkGLContext.h" 15 16static void cleanup(SkGLContext* glctx0, GrGLuint texID0, SkGLContext* glctx1, GrContext* grctx1, 17 const GrGLTextureInfo* grbackendtex1, GrEGLImage image1) { 18 if (glctx1) { 19 glctx1->makeCurrent(); 20 if (grctx1) { 21 if (grbackendtex1) { 22 GrGLGpu* gpu1 = static_cast<GrGLGpu*>(grctx1->getGpu()); 23 GrBackendObject handle = reinterpret_cast<GrBackendObject>(grbackendtex1); 24 gpu1->deleteTestingOnlyBackendTexture(handle, false); 25 } 26 grctx1->unref(); 27 } 28 if (GR_EGL_NO_IMAGE != image1) { 29 glctx1->destroyEGLImage(image1); 30 } 31 } 32 33 glctx0->makeCurrent(); 34 if (texID0) { 35 GR_GL_CALL(glctx0->gl(), DeleteTextures(1, &texID0)); 36 } 37} 38 39static void test_read_pixels(skiatest::Reporter* reporter, GrContext* context, 40 GrTexture* externalTexture, uint32_t expectedPixelValues[]) { 41 int pixelCnt = externalTexture->width() * externalTexture->height(); 42 SkAutoTMalloc<uint32_t> pixels(pixelCnt); 43 memset(pixels.get(), 0, sizeof(uint32_t)*pixelCnt); 44 bool read = externalTexture->readPixels(0, 0, externalTexture->width(), 45 externalTexture->height(), kRGBA_8888_GrPixelConfig, 46 pixels.get()); 47 if (!read) { 48 ERRORF(reporter, "Error reading external texture."); 49 } 50 for (int i = 0; i < pixelCnt; ++i) { 51 if (pixels.get()[i] != expectedPixelValues[i]) { 52 ERRORF(reporter, "Error, external texture pixel value %d should be 0x%08x," 53 " got 0x%08x.", i, expectedPixelValues[i], pixels.get()[i]); 54 break; 55 } 56 } 57} 58 59static void test_write_pixels(skiatest::Reporter* reporter, GrContext* context, 60 GrTexture* externalTexture) { 61 int pixelCnt = externalTexture->width() * externalTexture->height(); 62 SkAutoTMalloc<uint32_t> pixels(pixelCnt); 63 memset(pixels.get(), 0, sizeof(uint32_t)*pixelCnt); 64 bool write = externalTexture->writePixels(0, 0, 0, 0, kRGBA_8888_GrPixelConfig, pixels.get()); 65 REPORTER_ASSERT_MESSAGE(reporter, !write, "Should not be able to write to a EXTERNAL" 66 " texture."); 67} 68 69static void test_copy_surface(skiatest::Reporter* reporter, GrContext* context, 70 GrTexture* externalTexture, uint32_t expectedPixelValues[]) { 71 GrSurfaceDesc copyDesc; 72 copyDesc.fConfig = kRGBA_8888_GrPixelConfig; 73 copyDesc.fWidth = externalTexture->width(); 74 copyDesc.fHeight = externalTexture->height(); 75 copyDesc.fFlags = kRenderTarget_GrSurfaceFlag; 76 SkAutoTUnref<GrTexture> copy(context->textureProvider()->createTexture(copyDesc, true)); 77 context->copySurface(copy, externalTexture); 78 test_read_pixels(reporter, context, copy, expectedPixelValues); 79} 80 81DEF_GPUTEST_FOR_RENDERING_CONTEXTS(EGLImageTest, reporter, context0, glCtx0) { 82 // Try to create a second GL context and then check if the contexts have necessary 83 // extensions to run this test. 84 85 if (kGLES_GrGLStandard != glCtx0->gl()->fStandard) { 86 return; 87 } 88 GrGLGpu* gpu0 = static_cast<GrGLGpu*>(context0->getGpu()); 89 if (!gpu0->glCaps().externalTextureSupport()) { 90 return; 91 } 92 93 SkAutoTDelete<SkGLContext> glCtx1 = glCtx0->createNew(); 94 if (!glCtx1) { 95 return; 96 } 97 GrContext* context1 = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)glCtx1->gl()); 98 const GrGLTextureInfo* backendTexture1 = nullptr; 99 GrEGLImage image = GR_EGL_NO_IMAGE; 100 GrGLTextureInfo externalTexture; 101 externalTexture.fID = 0; 102 103 if (!context1) { 104 cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); 105 return; 106 } 107 108 if (!glCtx1->gl()->hasExtension("EGL_KHR_image") || 109 !glCtx1->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) { 110 cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); 111 return; 112 } 113 114 ///////////////////////////////// CONTEXT 1 /////////////////////////////////// 115 116 // Use GL Context 1 to create a texture unknown to GrContext. 117 context1->flush(); 118 GrGpu* gpu1 = context1->getGpu(); 119 static const int kSize = 100; 120 backendTexture1 = reinterpret_cast<const GrGLTextureInfo*>( 121 gpu1->createTestingOnlyBackendTexture(nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig)); 122 if (!backendTexture1 || !backendTexture1->fID) { 123 ERRORF(reporter, "Error creating texture for EGL Image"); 124 cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); 125 return; 126 } 127 if (GR_GL_TEXTURE_2D != backendTexture1->fTarget) { 128 ERRORF(reporter, "Expected backend texture to be 2D"); 129 cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); 130 return; 131 } 132 133 // Wrap the texture in an EGLImage 134 image = glCtx1->texture2DToEGLImage(backendTexture1->fID); 135 if (GR_EGL_NO_IMAGE == image) { 136 ERRORF(reporter, "Error creating EGL Image from texture"); 137 cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); 138 return; 139 } 140 141 // Populate the texture using GL context 1. Important to use TexSubImage as TexImage orphans 142 // the EGL image. Also, this must be done after creating the EGLImage as the texture 143 // contents may not be preserved when the image is created. 144 SkAutoTMalloc<uint32_t> pixels(kSize * kSize); 145 for (int i = 0; i < kSize*kSize; ++i) { 146 pixels.get()[i] = 0xDDAABBCC; 147 } 148 GR_GL_CALL(glCtx1->gl(), ActiveTexture(GR_GL_TEXTURE0)); 149 GR_GL_CALL(glCtx1->gl(), BindTexture(backendTexture1->fTarget, backendTexture1->fID)); 150 GR_GL_CALL(glCtx1->gl(), TexSubImage2D(backendTexture1->fTarget, 0, 0, 0, kSize, kSize, 151 GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, pixels.get())); 152 GR_GL_CALL(glCtx1->gl(), Finish()); 153 // We've been making direct GL calls in GL context 1, let GrContext 1 know its internal 154 // state is invalid. 155 context1->resetContext(); 156 157 ///////////////////////////////// CONTEXT 0 /////////////////////////////////// 158 159 // Make a new texture ID in GL Context 0 from the EGL Image 160 glCtx0->makeCurrent(); 161 externalTexture.fTarget = GR_GL_TEXTURE_EXTERNAL; 162 externalTexture.fID = glCtx0->eglImageToExternalTexture(image); 163 164 // Wrap this texture ID in a GrTexture 165 GrBackendTextureDesc externalDesc; 166 externalDesc.fConfig = kRGBA_8888_GrPixelConfig; 167 externalDesc.fWidth = kSize; 168 externalDesc.fHeight = kSize; 169 externalDesc.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture); 170 SkAutoTUnref<GrTexture> externalTextureObj( 171 context0->textureProvider()->wrapBackendTexture(externalDesc)); 172 if (!externalTextureObj) { 173 ERRORF(reporter, "Error wrapping external texture in GrTexture."); 174 cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); 175 return; 176 } 177 178 // Should not be able to wrap as a RT 179 externalDesc.fFlags = kRenderTarget_GrBackendTextureFlag; 180 SkAutoTUnref<GrTexture> externalTextureRTObj( 181 context0->textureProvider()->wrapBackendTexture(externalDesc)); 182 if (externalTextureRTObj) { 183 ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture as a RT."); 184 } 185 externalDesc.fFlags = kNone_GrBackendTextureFlag; 186 187 // Should not be able to wrap with a sample count 188 externalDesc.fSampleCnt = 4; 189 SkAutoTUnref<GrTexture> externalTextureMSAAObj( 190 context0->textureProvider()->wrapBackendTexture(externalDesc)); 191 if (externalTextureMSAAObj) { 192 ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture with MSAA."); 193 } 194 externalDesc.fSampleCnt = 0; 195 196 test_read_pixels(reporter, context0, externalTextureObj, pixels.get()); 197 198 test_write_pixels(reporter, context0, externalTextureObj); 199 200 test_copy_surface(reporter, context0, externalTextureObj, pixels.get()); 201 202 cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); 203} 204 205#endif 206