From cbdf8616f90118145209d25959d39f5d9737a3d6 Mon Sep 17 00:00:00 2001 From: Kenneth Russell Date: Tue, 9 Jul 2019 20:30:45 -0700 Subject: [PATCH] Support blitFramebuffer to and from IOSurface-backed textures. Extend validation to allow texture rectangle-backed textures as blitFramebuffer sources and destinations. Add end-to-end test covering this functionality, and run the IOSurfaceClientBufferTests against both ES2 and ES3. Bug: angleproject:3669 Change-Id: I7b8815a2c98072c12de45717afbba9e9b29ba253 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1694483 Commit-Queue: Kenneth Russell Reviewed-by: Jamie Madill --- src/libANGLE/FramebufferAttachment.cpp | 6 -- src/libANGLE/FramebufferAttachment.h | 6 ++ src/libANGLE/validationES2.cpp | 8 +- .../EGLIOSurfaceClientBufferTest.cpp | 85 ++++++++++++++++++- 4 files changed, 96 insertions(+), 9 deletions(-) diff --git a/src/libANGLE/FramebufferAttachment.cpp b/src/libANGLE/FramebufferAttachment.cpp index 8238541df..cad883dcc 100644 --- a/src/libANGLE/FramebufferAttachment.cpp +++ b/src/libANGLE/FramebufferAttachment.cpp @@ -178,12 +178,6 @@ GLuint FramebufferAttachment::id() const return mResource->getId(); } -const ImageIndex &FramebufferAttachment::getTextureImageIndex() const -{ - ASSERT(type() == GL_TEXTURE); - return mTarget.textureIndex(); -} - TextureTarget FramebufferAttachment::cubeMapFace() const { ASSERT(mType == GL_TEXTURE); diff --git a/src/libANGLE/FramebufferAttachment.h b/src/libANGLE/FramebufferAttachment.h index 10d8c990b..20c4d54aa 100644 --- a/src/libANGLE/FramebufferAttachment.h +++ b/src/libANGLE/FramebufferAttachment.h @@ -216,6 +216,12 @@ class FramebufferAttachmentObject : public angle::Subject virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0; }; +inline const ImageIndex &FramebufferAttachment::getTextureImageIndex() const +{ + ASSERT(type() == GL_TEXTURE); + return mTarget.textureIndex(); +} + inline Extents FramebufferAttachment::getSize() const { ASSERT(mResource); diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp index 4be4d2df8..49ee47da0 100644 --- a/src/libANGLE/validationES2.cpp +++ b/src/libANGLE/validationES2.cpp @@ -2671,7 +2671,9 @@ bool ValidateBlitFramebufferANGLE(Context *context, if (readColorAttachment && drawColorAttachment) { if (!(readColorAttachment->type() == GL_TEXTURE && - readColorAttachment->getTextureImageIndex().getType() == TextureType::_2D) && + (readColorAttachment->getTextureImageIndex().getType() == TextureType::_2D || + readColorAttachment->getTextureImageIndex().getType() == + TextureType::Rectangle)) && readColorAttachment->type() != GL_RENDERBUFFER && readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT) { @@ -2688,7 +2690,9 @@ bool ValidateBlitFramebufferANGLE(Context *context, if (attachment) { if (!(attachment->type() == GL_TEXTURE && - attachment->getTextureImageIndex().getType() == TextureType::_2D) && + (attachment->getTextureImageIndex().getType() == TextureType::_2D || + attachment->getTextureImageIndex().getType() == + TextureType::Rectangle)) && attachment->type() != GL_RENDERBUFFER && attachment->type() != GL_FRAMEBUFFER_DEFAULT) { diff --git a/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp b/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp index 7238aed7b..373d75da3 100644 --- a/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp +++ b/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp @@ -241,6 +241,74 @@ class IOSurfaceClientBufferTest : public ANGLETest ASSERT_GL_NO_ERROR(); } + void doBlitTest(bool ioSurfaceIsSource, int width, int height) + { + // Create IOSurface and bind it to a texture. + ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(width, height, 'BGRA', 4); + EGLSurface pbuffer; + GLTexture texture; + bindIOSurfaceToTexture(ioSurface, width, height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &pbuffer, + &texture); + + GLFramebuffer iosurfaceFbo; + glBindFramebuffer(GL_FRAMEBUFFER, iosurfaceFbo); + EXPECT_GL_NO_ERROR(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ANGLE, + texture, 0); + EXPECT_GL_NO_ERROR(); + EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE); + EXPECT_GL_NO_ERROR(); + + // Create another framebuffer with a regular renderbuffer. + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + EXPECT_GL_NO_ERROR(); + GLRenderbuffer rbo; + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + EXPECT_GL_NO_ERROR(); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); + EXPECT_GL_NO_ERROR(); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); + EXPECT_GL_NO_ERROR(); + EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE); + EXPECT_GL_NO_ERROR(); + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + EXPECT_GL_NO_ERROR(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + EXPECT_GL_NO_ERROR(); + + // Choose which is going to be the source and destination. + GLFramebuffer &src = ioSurfaceIsSource ? iosurfaceFbo : fbo; + GLFramebuffer &dst = ioSurfaceIsSource ? fbo : iosurfaceFbo; + + // Clear source to known color. + glBindFramebuffer(GL_FRAMEBUFFER, src); + glClearColor(1.0f / 255.0f, 2.0f / 255.0f, 3.0f / 255.0f, 4.0f / 255.0f); + EXPECT_GL_NO_ERROR(); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_GL_NO_ERROR(); + + // Blit to destination. + glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, dst); + glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, + GL_NEAREST); + + // Read back from destination. + glBindFramebuffer(GL_FRAMEBUFFER, dst); + GLColor expectedColor(1, 2, 3, 4); + EXPECT_PIXEL_COLOR_EQ(0, 0, expectedColor); + + // Unbind pbuffer and check content. + EGLBoolean result = eglReleaseTexImage(mDisplay, pbuffer, EGL_BACK_BUFFER); + EXPECT_EGL_TRUE(result); + EXPECT_EGL_SUCCESS(); + + result = eglDestroySurface(mDisplay, pbuffer); + EXPECT_EGL_TRUE(result); + EXPECT_EGL_SUCCESS(); + } + EGLConfig mConfig; EGLDisplay mDisplay; }; @@ -302,6 +370,9 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromR8IOSurface) // Test using R16 IOSurfaces for rendering TEST_P(IOSurfaceClientBufferTest, RenderToR16IOSurface) { + // This test only works on ES3. + ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3); + // HACK(cwallez@chromium.org) 'L016' doesn't seem to be an official pixel format but it works // sooooooo let's test using it ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'L016', 2); @@ -314,6 +385,18 @@ TEST_P(IOSurfaceClientBufferTest, RenderToR16IOSurface) // TODO(cwallez@chromium.org): Test using RGBA half float IOSurfaces ('RGhA') +// Test blitting from IOSurface +TEST_P(IOSurfaceClientBufferTest, BlitFromIOSurface) +{ + doBlitTest(true, 2, 2); +} + +// Test blitting to IOSurface +TEST_P(IOSurfaceClientBufferTest, BlitToIOSurface) +{ + doBlitTest(false, 2, 2); +} + // Test the validation errors for missing attributes for eglCreatePbufferFromClientBuffer with // IOSurface TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) @@ -726,4 +809,4 @@ TEST_P(IOSurfaceClientBufferTest, MakeCurrent) // TODO(cwallez@chromium.org): Test setting width and height to less than the IOSurface's work as // expected. -ANGLE_INSTANTIATE_TEST(IOSurfaceClientBufferTest, ES3_OPENGL()); +ANGLE_INSTANTIATE_TEST(IOSurfaceClientBufferTest, ES2_OPENGL(), ES3_OPENGL());