Index: tests/EGLImageTest.cpp |
diff --git a/tests/EGLImageTest.cpp b/tests/EGLImageTest.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..32e74f8e05ff6454530a96155c4573d2df17fc39 |
--- /dev/null |
+++ b/tests/EGLImageTest.cpp |
@@ -0,0 +1,169 @@ |
+/* |
+ * Copyright 2015 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "Test.h" |
+#if SK_SUPPORT_GPU |
+#include "GrContext.h" |
+#include "GrContextFactory.h" |
+#include "gl/GrGLGpu.h" |
+#include "gl/GrGLUtil.h" |
+#include "gl/SkGLContext.h" |
+ |
+static void cleanup(SkGLContext* glctx0, GrGLuint texID0, SkGLContext* glctx1, GrContext* grctx1, |
+ const GrGLTextureInfo* grbackendtex1, GrEGLImage image1) { |
+ if (glctx1) { |
+ glctx1->makeCurrent(); |
+ if (grctx1) { |
+ if (grbackendtex1) { |
+ GrGLGpu* gpu1 = static_cast<GrGLGpu*>(grctx1->getGpu()); |
+ GrBackendObject handle = reinterpret_cast<GrBackendObject>(grbackendtex1); |
+ gpu1->deleteTestingOnlyBackendTexture(handle, false); |
+ } |
+ grctx1->unref(); |
+ } |
+ if (GR_EGL_NO_IMAGE != image1) { |
+ glctx1->destroyEGLImage(image1); |
+ } |
+ glctx1->unref(); |
+ } |
+ |
+ glctx0->makeCurrent(); |
+ if (texID0) { |
+ GR_GL_CALL(glctx0->gl(), DeleteTextures(1, &texID0)); |
+ } |
+} |
+ |
+DEF_GPUTEST(EGLImageTest, reporter, factory) { |
+ for (int glCtxType = 0; glCtxType < GrContextFactory::kGLContextTypeCnt; ++glCtxType) { |
+ GrContextFactory::GLContextType type = (GrContextFactory::GLContextType)glCtxType; |
+ if (!GrContextFactory::IsRenderingGLContext(type)) { |
+ continue; |
+ } |
+ |
+ // Try to create a second GL context and then check if the contexts have necessary |
+ // extensions to run this test. |
+ |
+ GrContext* context0 = factory->get(type); |
+ if (!context0) { |
+ continue; |
+ } |
+ SkGLContext* glCtx0 = factory->getGLContext(type); |
+ SkASSERT(glCtx0); |
+ if (kGLES_GrGLStandard != glCtx0->gl()->fStandard) { |
+ continue; |
+ } |
+ GrGLGpu* gpu0 = static_cast<GrGLGpu*>(context0->getGpu()); |
+ if (!gpu0->glCaps().externalTextureSupport()) { |
+ continue; |
+ } |
+ |
+ SkGLContext* glCtx1 = glCtx0->createNew(); |
+ if (!glCtx1) { |
+ continue; |
+ } |
+ GrContext* context1 = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)glCtx1->gl()); |
+ const GrGLTextureInfo* backendTexture1 = nullptr; |
+ GrEGLImage image = GR_EGL_NO_IMAGE; |
+ GrGLTextureInfo externalTexture; |
+ externalTexture.fID = 0; |
+ |
+ if (!context1) { |
+ cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); |
+ continue; |
+ } |
+ |
+ if (!glCtx1->gl()->hasExtension("EGL_KHR_image") || |
+ !glCtx1->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) { |
+ cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); |
+ continue; |
+ } |
+ |
+///////////////////////////////// CONTEXT 1 /////////////////////////////////// |
+ |
+ // Use GL Context 1 to create a texture unknown to GrContext. |
+ context1->flush(); |
+ GrGpu* gpu1 = context1->getGpu(); |
+ static const int kSize = 100; |
+ backendTexture1 = reinterpret_cast<const GrGLTextureInfo*>( |
+ gpu1->createTestingOnlyBackendTexture(nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig)); |
+ if (!backendTexture1 || !backendTexture1->fID) { |
+ ERRORF(reporter, "Error creating texture for EGL Image"); |
+ cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); |
+ continue; |
+ } |
+ if (GR_GL_TEXTURE_2D != backendTexture1->fTarget) { |
+ ERRORF(reporter, "Expected backend texture to be 2D"); |
+ cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); |
+ continue; |
+ } |
+ |
+ // Wrap the texture in an EGLImage |
+ image = glCtx1->texture2DToEGLImage(backendTexture1->fID); |
+ if (GR_EGL_NO_IMAGE == image) { |
+ ERRORF(reporter, "Error creating EGL Image from texture"); |
+ cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); |
+ continue; |
+ } |
+ |
+ // Populate the texture using GL context 1. Important to use TexSubImage as TexImage orphans |
+ // the EGL image. Also, this must be done after creating the EGLImage as the texture |
+ // contents may not be preserved when the image is created. |
+ SkAutoTMalloc<uint32_t> pixels(kSize * kSize); |
+ for (int i = 0; i < kSize*kSize; ++i) { |
+ pixels.get()[i] = 0xDDAABBCC; |
+ } |
+ GR_GL_CALL(glCtx1->gl(), ActiveTexture(GR_GL_TEXTURE0)); |
+ GR_GL_CALL(glCtx1->gl(), BindTexture(backendTexture1->fTarget, backendTexture1->fID)); |
+ GR_GL_CALL(glCtx1->gl(), TexSubImage2D(backendTexture1->fTarget, 0, 0, 0, kSize, kSize, |
+ GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, pixels.get())); |
+ GR_GL_CALL(glCtx1->gl(), Finish()); |
+ // We've been making direct GL calls in GL context 1, let GrContext 1 know its internal |
+ // state is invalid. |
+ context1->resetContext(); |
+ |
+///////////////////////////////// CONTEXT 0 /////////////////////////////////// |
+ |
+ // Make a new texture ID in GL Context 0 from the EGL Image |
+ glCtx0->makeCurrent(); |
+ externalTexture.fTarget = GR_GL_TEXTURE_EXTERNAL; |
+ externalTexture.fID = glCtx0->eglImageToExternalTexture(image); |
+ |
+ // Wrap this texture ID in a GrTexture |
+ GrBackendTextureDesc externalDesc; |
+ externalDesc.fConfig = kRGBA_8888_GrPixelConfig; |
+ externalDesc.fWidth = kSize; |
+ externalDesc.fHeight = kSize; |
+ externalDesc.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture); |
+ SkAutoTUnref<GrTexture> externalTextureObj( |
+ context0->textureProvider()->wrapBackendTexture(externalDesc)); |
+ if (!externalTextureObj) { |
+ ERRORF(reporter, "Error wrapping external texture in GrTexture."); |
+ cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); |
+ continue; |
+ } |
+ |
+ // Read the pixels and see if we get the values set in GL context 1 |
+ memset(pixels.get(), 0, sizeof(uint32_t)*kSize*kSize); |
+ bool read = externalTextureObj->readPixels(0, 0, kSize, kSize, kRGBA_8888_GrPixelConfig, |
+ pixels.get()); |
+ if (!read) { |
+ ERRORF(reporter, "Error reading external texture."); |
+ cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); |
+ continue; |
+ } |
+ for (int i = 0; i < kSize*kSize; ++i) { |
+ if (pixels.get()[i] != 0xDDAABBCC) { |
+ ERRORF(reporter, "Error, external texture pixel value %d should be 0xDDAABBCC," |
+ " got 0x%08x.", pixels.get()[i]); |
+ break; |
+ } |
+ } |
+ cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image); |
+ } |
+} |
+ |
+#endif |