// // 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 #include #include #include #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(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 checkmap; std::fill_n(checkmap.begin(), (kWidth * kHeight), ChannelOrder(colorIn).asUint()); std::array 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 actual; glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, actual.data()); EXPECT_GL_NO_ERROR(); std::array 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(0)); return texture; } bool fillTexture(GLuint textureId, GLColor color) { std::array 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(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(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(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, 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, 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)); EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); glDeleteTextures(1, &texture); eglDestroySurface(mDisplay, windowSurface); 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)); EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context)); glDeleteTextures(1, &texture); eglDestroySurface(mDisplay, windowSurface); 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, context)); eglDestroySurface(mDisplay, windowSurface); osWindow->destroy(); OSWindow::Delete(&osWindow); } ANGLE_INSTANTIATE_TEST(EGLLockSurface3Test, WithNoFixture(ES2_VULKAN()), WithNoFixture(ES3_VULKAN()));