| // |
| // Copyright 2021 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // EGLLockSurface3Test.cpp: |
| // EGL extension EGL_KHR_lock_surface |
| // |
| |
| #include <gtest/gtest.h> |
| |
| #include <chrono> |
| #include <iostream> |
| #include <thread> |
| #include "test_utils/ANGLETest.h" |
| #include "test_utils/gl_raii.h" |
| #include "util/EGLWindow.h" |
| #include "util/OSWindow.h" |
| |
| using namespace std::chrono_literals; |
| |
| using namespace angle; |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLLockSurface3Test); |
| |
| class EGLLockSurface3Test : public ANGLETest<> |
| { |
| public: |
| EGLLockSurface3Test() : mDisplay(EGL_NO_DISPLAY) {} |
| |
| void testSetUp() override |
| { |
| mMajorVersion = GetParam().majorVersion; |
| |
| EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; |
| mDisplay = eglGetPlatformDisplayEXT( |
| EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs); |
| EXPECT_NE(mDisplay, EGL_NO_DISPLAY); |
| EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); |
| } |
| |
| bool supportsLockSurface3Extension() |
| { |
| return IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_lock_surface3"); |
| } |
| |
| void testTearDown() override |
| { |
| if (mDisplay != EGL_NO_DISPLAY) |
| { |
| eglTerminate(mDisplay); |
| eglReleaseThread(); |
| mDisplay = EGL_NO_DISPLAY; |
| } |
| ASSERT_EGL_SUCCESS() << "Error during test TearDown"; |
| } |
| |
| // This will work for Windows and linux systemsAny other BGRA systems will have to be included. |
| GLColor ChannelOrder(GLColor colorIn) |
| { |
| GLColor color = colorIn; |
| if (IsWindows() || IsLinux()) |
| { // BGRA channel order |
| color.R = colorIn.B; |
| color.B = colorIn.R; |
| } |
| return color; |
| } |
| |
| void fillBitMapRGBA32(GLColor colorIn, uint32_t *bitMapPtr, EGLint stride) |
| { |
| for (uint32_t y = 0; y < kHeight; y++) |
| { |
| uint32_t *pixelPtr = bitMapPtr + (y * (stride / 4)); |
| for (uint32_t x = 0; x < kWidth; x++) |
| { |
| pixelPtr[x] = ChannelOrder(colorIn).asUint(); |
| } |
| } |
| } |
| |
| bool checkBitMapRGBA32(GLColor colorIn, uint32_t *bitMapPtr, EGLint stride) |
| { |
| std::array<uint32_t, (kWidth * kHeight)> checkmap; |
| std::fill_n(checkmap.begin(), (kWidth * kHeight), ChannelOrder(colorIn).asUint()); |
| |
| std::array<uint32_t, (kWidth * kHeight)> bitmap; |
| for (uint32_t i = 0; i < (kWidth * kHeight); i++) |
| { |
| bitmap[i] = bitMapPtr[i]; |
| } |
| |
| if (bitmap != checkmap) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool checkSurfaceRGBA32(GLColor color) |
| { |
| std::array<uint32_t, (kWidth * kHeight)> actual; |
| glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, actual.data()); |
| EXPECT_GL_NO_ERROR(); |
| |
| std::array<uint32_t, (kWidth * kHeight)> checkmap; |
| std::fill_n(checkmap.begin(), (kWidth * kHeight), color.asUint()); |
| |
| if (actual != checkmap) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| GLuint createTexture() |
| { |
| GLuint texture = 0; |
| glGenTextures(1, &texture); |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, |
| nullptr); |
| EXPECT_GL_NO_ERROR(); |
| glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight); |
| EXPECT_GL_NO_ERROR(); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| EXPECT_NE(texture, static_cast<GLuint>(0)); |
| return texture; |
| } |
| |
| bool fillTexture(GLuint textureId, GLColor color) |
| { |
| std::array<GLuint, (kWidth * kHeight)> pixels; |
| std::fill_n(pixels.begin(), (kWidth * kHeight), color.asUint()); |
| glBindTexture(GL_TEXTURE_2D, textureId); |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, |
| static_cast<void *>(pixels.data())); |
| EXPECT_GL_NO_ERROR(); |
| return true; |
| } |
| |
| void renderTexture(GLuint textureId) |
| { |
| const char *kVertexShader = R"( |
| precision highp float; |
| attribute vec4 position; |
| varying vec2 texcoord; |
| |
| void main() |
| { |
| gl_Position = vec4(position.xy, 0.0, 1.0); |
| texcoord = (position.xy * 0.5) + 0.5; |
| } |
| )"; |
| const char *kFragmentShader = R"( |
| precision highp float; |
| uniform sampler2D tex; |
| varying vec2 texcoord; |
| |
| void main() |
| { |
| gl_FragColor = texture2D(tex, texcoord); |
| } |
| )"; |
| |
| ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader); |
| glUseProgram(program); |
| glBindTexture(GL_TEXTURE_2D, textureId); |
| glActiveTexture(GL_TEXTURE0); |
| GLint texture2DUniformLocation = glGetUniformLocation(program, "tex"); |
| glUniform1i(texture2DUniformLocation, 0); |
| drawQuad(program, "position", 0.5f); |
| glDeleteProgram(program); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| int mMajorVersion = 2; |
| EGLDisplay mDisplay = EGL_NO_DISPLAY; |
| |
| static constexpr EGLint kWidth = 5; |
| static constexpr EGLint kHeight = 5; |
| }; |
| |
| // Create parity between eglQuerySurface and eglQuerySurface64KHR |
| TEST_P(EGLLockSurface3Test, QuerySurfaceAndQuerySurface64Parity) |
| { |
| ANGLE_SKIP_TEST_IF(!supportsLockSurface3Extension()); |
| |
| EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT; |
| EGLint attribs[] = {EGL_RED_SIZE, |
| 8, |
| EGL_GREEN_SIZE, |
| 8, |
| EGL_BLUE_SIZE, |
| 8, |
| EGL_ALPHA_SIZE, |
| 8, |
| EGL_RENDERABLE_TYPE, |
| clientVersion, |
| EGL_SURFACE_TYPE, |
| (EGL_PBUFFER_BIT | EGL_LOCK_SURFACE_BIT_KHR), |
| EGL_NONE}; |
| EGLint count = 0; |
| EGLConfig config = EGL_NO_CONFIG_KHR; |
| EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, attribs, &config, 1, &count)); |
| EXPECT_GT(count, 0); |
| ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR); |
| |
| EGLint pBufferAttribs[] = {EGL_WIDTH, kWidth, EGL_HEIGHT, kHeight, EGL_NONE}; |
| EGLSurface pBufferSurface = eglCreatePbufferSurface(mDisplay, config, pBufferAttribs); |
| EXPECT_NE(pBufferSurface, EGL_NO_SURFACE); |
| |
| EGLint width = 0; |
| EGLAttribKHR width64 = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, pBufferSurface, EGL_WIDTH, &width)); |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_WIDTH, &width64)); |
| EXPECT_EQ(static_cast<EGLAttribKHR>(width), width64); |
| |
| EGLint height = 0; |
| EGLAttribKHR height64 = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, pBufferSurface, EGL_HEIGHT, &height)); |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_HEIGHT, &height64)); |
| EXPECT_EQ(static_cast<EGLAttribKHR>(height), height64); |
| |
| EXPECT_EGL_TRUE(eglDestroySurface(mDisplay, pBufferSurface)); |
| } |
| |
| // Create PBufferSurface, Lock, check all the attributes, unlock. |
| TEST_P(EGLLockSurface3Test, AttributeTest) |
| { |
| ANGLE_SKIP_TEST_IF(!supportsLockSurface3Extension()); |
| |
| EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT; |
| EGLint attribs[] = {EGL_RED_SIZE, |
| 8, |
| EGL_GREEN_SIZE, |
| 8, |
| EGL_BLUE_SIZE, |
| 8, |
| EGL_ALPHA_SIZE, |
| 8, |
| EGL_RENDERABLE_TYPE, |
| clientVersion, |
| EGL_SURFACE_TYPE, |
| (EGL_PBUFFER_BIT | EGL_LOCK_SURFACE_BIT_KHR), |
| EGL_NONE}; |
| EGLint count = 0; |
| EGLConfig config = EGL_NO_CONFIG_KHR; |
| EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, attribs, &config, 1, &count)); |
| EXPECT_GT(count, 0); |
| ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR); |
| |
| EGLint pBufferAttribs[] = {EGL_WIDTH, kWidth, EGL_HEIGHT, kHeight, EGL_NONE}; |
| EGLSurface pBufferSurface = eglCreatePbufferSurface(mDisplay, config, pBufferAttribs); |
| EXPECT_NE(pBufferSurface, EGL_NO_SURFACE); |
| |
| EGLint lockAttribs[] = {EGL_LOCK_USAGE_HINT_KHR, EGL_WRITE_SURFACE_BIT_KHR, EGL_NONE}; |
| EXPECT_EGL_TRUE(eglLockSurfaceKHR(mDisplay, pBufferSurface, lockAttribs)); |
| |
| EGLAttribKHR bitMapPtr = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_BITMAP_POINTER_KHR, &bitMapPtr)); |
| EXPECT_NE(bitMapPtr, 0); |
| |
| EGLAttribKHR bitMapPitch = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_BITMAP_PITCH_KHR, &bitMapPitch)); |
| EXPECT_NE(bitMapPitch, 0); |
| |
| EGLAttribKHR bitMapOrigin = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_BITMAP_ORIGIN_KHR, &bitMapOrigin)); |
| EXPECT_TRUE((bitMapOrigin == EGL_LOWER_LEFT_KHR) || (bitMapOrigin == EGL_UPPER_LEFT_KHR)); |
| |
| EGLAttribKHR bitMapPixelRedOffset = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_RED_OFFSET_KHR, |
| &bitMapPixelRedOffset)); |
| EXPECT_TRUE((bitMapPixelRedOffset == 0) || (bitMapPixelRedOffset == 16)); |
| |
| EGLAttribKHR bitMapPixelGreenOffset = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR( |
| mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR, &bitMapPixelGreenOffset)); |
| EXPECT_EQ(bitMapPixelGreenOffset, 8); |
| |
| EGLAttribKHR bitMapPixelBlueOffset = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR, |
| &bitMapPixelBlueOffset)); |
| EXPECT_TRUE((bitMapPixelBlueOffset == 16) || (bitMapPixelBlueOffset == 0)); |
| |
| EGLAttribKHR bitMapPixelAlphaOffset = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR( |
| mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR, &bitMapPixelAlphaOffset)); |
| EXPECT_EQ(bitMapPixelAlphaOffset, 24); |
| |
| EGLAttribKHR bitMapPixelLuminanceOffset = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR(mDisplay, pBufferSurface, |
| EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR, |
| &bitMapPixelLuminanceOffset)); |
| EXPECT_EQ(bitMapPixelLuminanceOffset, 0); |
| |
| EGLAttribKHR bitMapPixelSize = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_SIZE_KHR, |
| &bitMapPixelSize)); |
| EXPECT_EQ(bitMapPixelSize, 32); |
| |
| EGLint bitMapPitchInt = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface(mDisplay, pBufferSurface, EGL_BITMAP_PITCH_KHR, &bitMapPitchInt)); |
| EXPECT_NE(bitMapPitchInt, 0); |
| |
| EGLint bitMapOriginInt = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface(mDisplay, pBufferSurface, EGL_BITMAP_ORIGIN_KHR, &bitMapOriginInt)); |
| EXPECT_TRUE((bitMapOriginInt == EGL_LOWER_LEFT_KHR) || (bitMapOriginInt == EGL_UPPER_LEFT_KHR)); |
| |
| EGLint bitMapPixelRedOffsetInt = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_RED_OFFSET_KHR, |
| &bitMapPixelRedOffsetInt)); |
| EXPECT_TRUE((bitMapPixelRedOffsetInt == 0) || (bitMapPixelRedOffsetInt == 16)); |
| |
| EGLint bitMapPixelGreenOffsetInt = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR, |
| &bitMapPixelGreenOffsetInt)); |
| EXPECT_EQ(bitMapPixelGreenOffsetInt, 8); |
| |
| EGLint bitMapPixelBlueOffsetInt = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR, |
| &bitMapPixelBlueOffsetInt)); |
| EXPECT_TRUE((bitMapPixelBlueOffsetInt == 16) || (bitMapPixelBlueOffsetInt == 0)); |
| |
| EGLint bitMapPixelAlphaOffsetInt = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR, |
| &bitMapPixelAlphaOffsetInt)); |
| EXPECT_EQ(bitMapPixelAlphaOffsetInt, 24); |
| |
| EGLint bitMapPixelLuminanceOffsetInt = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR, |
| &bitMapPixelLuminanceOffsetInt)); |
| EXPECT_EQ(bitMapPixelLuminanceOffsetInt, 0); |
| |
| EGLint bitMapPixelSizeInt = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface(mDisplay, pBufferSurface, EGL_BITMAP_PIXEL_SIZE_KHR, &bitMapPixelSizeInt)); |
| EXPECT_EQ(bitMapPixelSizeInt, 32); |
| |
| EXPECT_EGL_TRUE(eglUnlockSurfaceKHR(mDisplay, pBufferSurface)); |
| } |
| |
| // Create PBufferSurface, glClear Green, Draw red quad, Lock, check buffer for red, |
| // Write white pixels, Unlock, Test pixels for white |
| TEST_P(EGLLockSurface3Test, PbufferSurfaceReadWriteTest) |
| { |
| ANGLE_SKIP_TEST_IF(!supportsLockSurface3Extension()); |
| |
| EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT; |
| EGLint attribs[] = {EGL_RED_SIZE, |
| 8, |
| EGL_GREEN_SIZE, |
| 8, |
| EGL_BLUE_SIZE, |
| 8, |
| EGL_ALPHA_SIZE, |
| 8, |
| EGL_RENDERABLE_TYPE, |
| clientVersion, |
| EGL_SURFACE_TYPE, |
| (EGL_PBUFFER_BIT | EGL_LOCK_SURFACE_BIT_KHR), |
| EGL_NONE}; |
| EGLint count = 0; |
| EGLConfig config = EGL_NO_CONFIG_KHR; |
| EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, attribs, &config, 1, &count)); |
| ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR); |
| EXPECT_GT(count, 0); |
| |
| EGLint pBufferAttribs[] = {EGL_WIDTH, kWidth, EGL_HEIGHT, kHeight, EGL_NONE}; |
| EGLSurface pBufferSurface = EGL_NO_SURFACE; |
| pBufferSurface = eglCreatePbufferSurface(mDisplay, config, pBufferAttribs); |
| EXPECT_NE(pBufferSurface, EGL_NO_SURFACE); |
| |
| EGLint ctxAttribs[] = {EGL_CONTEXT_MAJOR_VERSION, mMajorVersion, EGL_NONE}; |
| EGLContext context = eglCreateContext(mDisplay, config, nullptr, ctxAttribs); |
| EXPECT_NE(context, EGL_NO_CONTEXT); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, pBufferSurface, pBufferSurface, context)); |
| ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; |
| |
| glClearColor(kFloatGreen.R, kFloatGreen.G, kFloatGreen.B, kFloatGreen.A); |
| glClear(GL_COLOR_BUFFER_BIT); |
| ASSERT_GL_NO_ERROR() << "glClear failed"; |
| |
| const GLColor drawColor = GLColor::red; |
| GLuint texture = createTexture(); |
| EXPECT_TRUE(fillTexture(texture, drawColor)); |
| renderTexture(texture); |
| glFinish(); |
| ASSERT_GL_NO_ERROR() << "glFinish failed"; |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); |
| |
| EGLint lockAttribs[] = {EGL_LOCK_USAGE_HINT_KHR, EGL_WRITE_SURFACE_BIT_KHR, |
| EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, EGL_NONE}; |
| EXPECT_EGL_TRUE(eglLockSurfaceKHR(mDisplay, pBufferSurface, lockAttribs)); |
| |
| EGLAttribKHR bitMap = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_BITMAP_POINTER_KHR, &bitMap)); |
| EGLAttribKHR bitMapPitch = 0; |
| uint32_t *bitMapPtr = (uint32_t *)(bitMap); |
| EXPECT_EGL_TRUE( |
| eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_BITMAP_PITCH_KHR, &bitMapPitch)); |
| |
| EXPECT_TRUE(checkBitMapRGBA32(drawColor, bitMapPtr, bitMapPitch)); |
| |
| const GLColor fillColor = GLColor::white; |
| fillBitMapRGBA32(fillColor, bitMapPtr, bitMapPitch); |
| |
| EXPECT_EGL_TRUE(eglUnlockSurfaceKHR(mDisplay, pBufferSurface)); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, pBufferSurface, pBufferSurface, context)); |
| ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; |
| |
| EXPECT_TRUE(checkSurfaceRGBA32(fillColor)); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); |
| EXPECT_EGL_TRUE(eglDestroySurface(mDisplay, pBufferSurface)); |
| EXPECT_EGL_TRUE(eglDestroyContext(mDisplay, context)); |
| } |
| |
| // Create PBufferSurface, glClear Green, Lock, check buffer for green, Write white pixels, |
| // Unlock, Test pixels for white. |
| // This expects that a glClear() alone is sufficient to pre-color the Surface |
| TEST_P(EGLLockSurface3Test, PbufferSurfaceReadWriteDeferredCleaarTest) |
| { |
| ANGLE_SKIP_TEST_IF(!supportsLockSurface3Extension()); |
| |
| EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT; |
| EGLint attribs[] = {EGL_RED_SIZE, |
| 8, |
| EGL_GREEN_SIZE, |
| 8, |
| EGL_BLUE_SIZE, |
| 8, |
| EGL_ALPHA_SIZE, |
| 8, |
| EGL_RENDERABLE_TYPE, |
| clientVersion, |
| EGL_SURFACE_TYPE, |
| (EGL_PBUFFER_BIT | EGL_LOCK_SURFACE_BIT_KHR), |
| EGL_NONE}; |
| EGLint count = 0; |
| EGLConfig config = EGL_NO_CONFIG_KHR; |
| EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, attribs, &config, 1, &count)); |
| ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR); |
| EXPECT_GT(count, 0); |
| |
| EGLint pBufferAttribs[] = {EGL_WIDTH, kWidth, EGL_HEIGHT, kHeight, EGL_NONE}; |
| EGLSurface pBufferSurface = EGL_NO_SURFACE; |
| pBufferSurface = eglCreatePbufferSurface(mDisplay, config, pBufferAttribs); |
| EXPECT_NE(pBufferSurface, EGL_NO_SURFACE); |
| |
| EGLint ctxAttribs[] = {EGL_CONTEXT_MAJOR_VERSION, mMajorVersion, EGL_NONE}; |
| EGLContext context = eglCreateContext(mDisplay, config, nullptr, ctxAttribs); |
| EXPECT_NE(context, EGL_NO_CONTEXT); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, pBufferSurface, pBufferSurface, context)); |
| ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; |
| |
| const GLColor clearColor = GLColor::green; |
| glClearColor(kFloatGreen.R, kFloatGreen.G, kFloatGreen.B, kFloatGreen.A); |
| glClear(GL_COLOR_BUFFER_BIT); |
| ASSERT_GL_NO_ERROR() << "glClear failed"; |
| |
| const GLColor drawColor = clearColor; |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); |
| |
| EGLint lockAttribs[] = {EGL_LOCK_USAGE_HINT_KHR, EGL_WRITE_SURFACE_BIT_KHR, |
| EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, EGL_NONE}; |
| EXPECT_EGL_TRUE(eglLockSurfaceKHR(mDisplay, pBufferSurface, lockAttribs)); |
| |
| EGLAttribKHR bitMap = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_BITMAP_POINTER_KHR, &bitMap)); |
| EGLAttribKHR bitMapPitch = 0; |
| uint32_t *bitMapPtr = (uint32_t *)(bitMap); |
| EXPECT_EGL_TRUE( |
| eglQuerySurface64KHR(mDisplay, pBufferSurface, EGL_BITMAP_PITCH_KHR, &bitMapPitch)); |
| |
| EXPECT_TRUE(checkBitMapRGBA32(drawColor, bitMapPtr, bitMapPitch)); |
| |
| const GLColor fillColor = GLColor::white; |
| fillBitMapRGBA32(fillColor, bitMapPtr, bitMapPitch); |
| |
| EXPECT_EGL_TRUE(eglUnlockSurfaceKHR(mDisplay, pBufferSurface)); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, pBufferSurface, pBufferSurface, context)); |
| ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; |
| |
| EXPECT_TRUE(checkSurfaceRGBA32(fillColor)); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); |
| EXPECT_EGL_TRUE(eglDestroySurface(mDisplay, pBufferSurface)); |
| EXPECT_EGL_TRUE(eglDestroyContext(mDisplay, context)); |
| } |
| |
| // Create WindowSurface, Clear Color to GREEN, draw red quad, Lock with PRESERVE_PIXELS, |
| // read/check pixels, Unlock. |
| TEST_P(EGLLockSurface3Test, WindowSurfaceReadTest) |
| { |
| ANGLE_SKIP_TEST_IF(!supportsLockSurface3Extension()); |
| |
| EGLint configAttribs[] = {EGL_RED_SIZE, |
| 8, |
| EGL_GREEN_SIZE, |
| 8, |
| EGL_BLUE_SIZE, |
| 8, |
| EGL_ALPHA_SIZE, |
| 8, |
| EGL_RENDERABLE_TYPE, |
| (mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT), |
| EGL_SURFACE_TYPE, |
| (EGL_WINDOW_BIT | EGL_LOCK_SURFACE_BIT_KHR), |
| EGL_NONE}; |
| EGLint count = 0; |
| EGLConfig config = EGL_NO_CONFIG_KHR; |
| EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, configAttribs, &config, 1, &count)); |
| ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR); |
| EXPECT_GT(count, 0); |
| |
| OSWindow *osWindow = OSWindow::New(); |
| osWindow->initialize("LockSurfaceTest", kWidth, kHeight); |
| EGLint winAttribs[] = {EGL_NONE}; |
| EGLSurface windowSurface = |
| eglCreateWindowSurface(mDisplay, config, osWindow->getNativeWindow(), winAttribs); |
| EXPECT_NE(windowSurface, EGL_NO_SURFACE); |
| |
| EGLint ctxAttribs[] = {EGL_CONTEXT_MAJOR_VERSION, mMajorVersion, EGL_NONE}; |
| EGLContext context = eglCreateContext(mDisplay, config, nullptr, ctxAttribs); |
| EXPECT_NE(context, EGL_NO_CONTEXT); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context)); |
| ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; |
| |
| glClearColor(kFloatGreen.R, kFloatGreen.G, kFloatGreen.B, kFloatGreen.A); |
| glClear(GL_COLOR_BUFFER_BIT); |
| ASSERT_GL_NO_ERROR() << "glClear failed"; |
| |
| const GLColor drawColor = GLColor::red; |
| GLuint texture = createTexture(); |
| EXPECT_TRUE(fillTexture(texture, drawColor)); |
| renderTexture(texture); |
| glFinish(); |
| ASSERT_GL_NO_ERROR() << "glFinish failed"; |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); |
| |
| EGLint lockAttribs[] = {EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR, |
| EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, EGL_NONE}; |
| EXPECT_EGL_TRUE(eglLockSurfaceKHR(mDisplay, windowSurface, lockAttribs)); |
| |
| EGLAttribKHR bitMap = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR(mDisplay, windowSurface, EGL_BITMAP_POINTER_KHR, &bitMap)); |
| EGLAttribKHR bitMapPitch = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface64KHR(mDisplay, windowSurface, EGL_BITMAP_PITCH_KHR, &bitMapPitch)); |
| |
| uint32_t *bitMapPtr = (uint32_t *)(bitMap); |
| EXPECT_TRUE(checkBitMapRGBA32(drawColor, bitMapPtr, bitMapPitch)); |
| |
| EXPECT_TRUE(eglUnlockSurfaceKHR(mDisplay, windowSurface)); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context)); |
| ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; |
| EXPECT_TRUE(checkSurfaceRGBA32(drawColor)); |
| EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, windowSurface)); |
| |
| glDeleteTextures(1, &texture); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); |
| EXPECT_EGL_TRUE(eglDestroySurface(mDisplay, windowSurface)); |
| EXPECT_EGL_TRUE(eglDestroyContext(mDisplay, context)); |
| osWindow->destroy(); |
| OSWindow::Delete(&osWindow); |
| } |
| |
| // Test default msaa surface resolve path. |
| TEST_P(EGLLockSurface3Test, WindowMsaaSurfaceReadTest) |
| { |
| ANGLE_SKIP_TEST_IF(!supportsLockSurface3Extension()); |
| |
| EGLint configAttribs[] = {EGL_RED_SIZE, |
| 8, |
| EGL_GREEN_SIZE, |
| 8, |
| EGL_BLUE_SIZE, |
| 8, |
| EGL_ALPHA_SIZE, |
| 8, |
| EGL_RENDERABLE_TYPE, |
| (mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT), |
| EGL_SAMPLE_BUFFERS, |
| 1, |
| EGL_SAMPLES, |
| 4, |
| EGL_SURFACE_TYPE, |
| (EGL_WINDOW_BIT | EGL_LOCK_SURFACE_BIT_KHR), |
| EGL_NONE}; |
| EGLint count = 0; |
| EGLConfig config = EGL_NO_CONFIG_KHR; |
| EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, configAttribs, &config, 1, &count)); |
| ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR); |
| EXPECT_GT(count, 0); |
| |
| OSWindow *osWindow = OSWindow::New(); |
| osWindow->initialize("LockSurfaceTest", kWidth, kHeight); |
| EGLint winAttribs[] = {EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER, EGL_NONE}; |
| EGLSurface windowSurface = |
| eglCreateWindowSurface(mDisplay, config, osWindow->getNativeWindow(), winAttribs); |
| EXPECT_NE(windowSurface, EGL_NO_SURFACE); |
| |
| EGLint ctxAttribs[] = {EGL_CONTEXT_MAJOR_VERSION, mMajorVersion, EGL_NONE}; |
| EGLContext context = eglCreateContext(mDisplay, config, nullptr, ctxAttribs); |
| EXPECT_NE(context, EGL_NO_CONTEXT); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context)); |
| ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; |
| |
| glClearColor(kFloatGreen.R, kFloatGreen.G, kFloatGreen.B, kFloatGreen.A); |
| glClear(GL_COLOR_BUFFER_BIT); |
| ASSERT_GL_NO_ERROR() << "glClear failed"; |
| |
| const GLColor drawColor = GLColor::red; |
| GLuint texture = createTexture(); |
| EXPECT_TRUE(fillTexture(texture, drawColor)); |
| renderTexture(texture); |
| eglSwapBuffers(mDisplay, windowSurface); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); |
| |
| EGLint lockAttribs[] = {EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR, |
| EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, EGL_NONE}; |
| EXPECT_EGL_TRUE(eglLockSurfaceKHR(mDisplay, windowSurface, lockAttribs)); |
| |
| EGLAttribKHR bitMap = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR(mDisplay, windowSurface, EGL_BITMAP_POINTER_KHR, &bitMap)); |
| EGLAttribKHR bitMapPitch = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface64KHR(mDisplay, windowSurface, EGL_BITMAP_PITCH_KHR, &bitMapPitch)); |
| |
| uint32_t *bitMapPtr = (uint32_t *)(bitMap); |
| EXPECT_TRUE(checkBitMapRGBA32(drawColor, bitMapPtr, bitMapPitch)); |
| |
| EXPECT_TRUE(eglUnlockSurfaceKHR(mDisplay, windowSurface)); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context)); |
| ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; |
| EXPECT_TRUE(checkSurfaceRGBA32(drawColor)); |
| EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, windowSurface)); |
| |
| glDeleteTextures(1, &texture); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); |
| EXPECT_EGL_TRUE(eglDestroySurface(mDisplay, windowSurface)); |
| EXPECT_EGL_TRUE(eglDestroyContext(mDisplay, context)); |
| osWindow->destroy(); |
| OSWindow::Delete(&osWindow); |
| } |
| |
| // Create WindowSurface, Lock surface, Write pixels red, Unlock, check pixels, |
| // then swapbuffers to visually check. |
| TEST_P(EGLLockSurface3Test, WindowSurfaceWritePreserveTest) |
| { |
| ANGLE_SKIP_TEST_IF(!supportsLockSurface3Extension()); |
| |
| EGLint attribs[] = {EGL_RED_SIZE, |
| 8, |
| EGL_GREEN_SIZE, |
| 8, |
| EGL_BLUE_SIZE, |
| 8, |
| EGL_ALPHA_SIZE, |
| 8, |
| EGL_RENDERABLE_TYPE, |
| (mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT), |
| EGL_SURFACE_TYPE, |
| (EGL_WINDOW_BIT | EGL_LOCK_SURFACE_BIT_KHR), |
| EGL_NONE}; |
| EGLint count = 0; |
| EGLConfig config = EGL_NO_CONFIG_KHR; |
| EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, attribs, &config, 1, &count)); |
| ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR); |
| EXPECT_GT(count, 0); |
| |
| OSWindow *osWindow = OSWindow::New(); |
| osWindow->initialize("LockSurfaceTest", kWidth, kHeight); |
| EGLint winAttribs[] = {EGL_NONE}; |
| EGLSurface windowSurface = |
| eglCreateWindowSurface(mDisplay, config, osWindow->getNativeWindow(), winAttribs); |
| EXPECT_NE(windowSurface, EGL_NO_SURFACE); |
| |
| EGLint ctxAttribs[] = {EGL_CONTEXT_MAJOR_VERSION, mMajorVersion, EGL_NONE}; |
| EGLContext context = eglCreateContext(mDisplay, config, nullptr, ctxAttribs); |
| EXPECT_NE(context, EGL_NO_CONTEXT); |
| |
| EGLint lockAttribs[] = {EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR, EGL_NONE}; |
| EXPECT_EGL_TRUE(eglLockSurfaceKHR(mDisplay, windowSurface, lockAttribs)); |
| |
| EGLAttribKHR bitMap = 0; |
| EXPECT_EGL_TRUE(eglQuerySurface64KHR(mDisplay, windowSurface, EGL_BITMAP_POINTER_KHR, &bitMap)); |
| EGLAttribKHR bitMapPitch = 0; |
| EXPECT_EGL_TRUE( |
| eglQuerySurface64KHR(mDisplay, windowSurface, EGL_BITMAP_PITCH_KHR, &bitMapPitch)); |
| uint32_t *bitMapPtr = (uint32_t *)(bitMap); |
| |
| const GLColor fillColor = GLColor::red; |
| fillBitMapRGBA32(fillColor, bitMapPtr, bitMapPitch); |
| |
| EXPECT_EGL_TRUE(eglUnlockSurfaceKHR(mDisplay, windowSurface)); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context)); |
| ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed."; |
| EXPECT_TRUE(checkSurfaceRGBA32(fillColor)); |
| EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, windowSurface)); |
| |
| EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); |
| EXPECT_EGL_TRUE(eglDestroySurface(mDisplay, windowSurface)); |
| EXPECT_EGL_TRUE(eglDestroyContext(mDisplay, context)); |
| osWindow->destroy(); |
| OSWindow::Delete(&osWindow); |
| } |
| |
| ANGLE_INSTANTIATE_TEST(EGLLockSurface3Test, |
| WithNoFixture(ES2_VULKAN()), |
| WithNoFixture(ES3_VULKAN())); |