| // |
| // Copyright 2024 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. |
| // |
| |
| #include "test_utils/ANGLETest.h" |
| #include "test_utils/gl_raii.h" |
| |
| namespace angle |
| { |
| class TiledRenderingTest : public ANGLETest<> |
| { |
| protected: |
| TiledRenderingTest() |
| { |
| setWindowWidth(128); |
| setWindowHeight(128); |
| setConfigRedBits(8); |
| setConfigGreenBits(8); |
| setConfigBlueBits(8); |
| setConfigAlphaBits(8); |
| } |
| }; |
| |
| // Validate that the extension entry points generate errors when the extension is not available. |
| TEST_P(TiledRenderingTest, ExtensionDisabled) |
| { |
| ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_QCOM_tiled_rendering")); |
| glStartTilingQCOM(0, 0, 1, 1, GL_COLOR_BUFFER_BIT0_QCOM); |
| EXPECT_GL_ERROR(GL_INVALID_OPERATION); |
| glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); |
| EXPECT_GL_ERROR(GL_INVALID_OPERATION); |
| } |
| |
| // Test that tiled rendering can be stared and stopped. Verify that only pixels in bounds are |
| // written. |
| TEST_P(TiledRenderingTest, BasicUsage) |
| { |
| ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_tiled_rendering")); |
| |
| ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue()); |
| |
| glClearColor(0, 0, 0, 0); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| glStartTilingQCOM(10, 12, 15, 17, GL_COLOR_BUFFER_BIT0_QCOM); |
| |
| drawQuad(program, essl1_shaders::PositionAttrib(), 0); |
| |
| glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); |
| |
| const int w = getWindowWidth(); |
| const int h = getWindowHeight(); |
| |
| EXPECT_PIXEL_RECT_EQ(10, 12, 15, 17, GLColor::blue); |
| EXPECT_PIXEL_RECT_EQ(0, 0, w, 12, GLColor::transparentBlack); |
| EXPECT_PIXEL_RECT_EQ(0, 12 + 17, w, h - 12 - 17, GLColor::transparentBlack); |
| EXPECT_PIXEL_RECT_EQ(0, 0, 10, h, GLColor::transparentBlack); |
| EXPECT_PIXEL_RECT_EQ(10 + 15, 0, w - 10 - 15, h, GLColor::transparentBlack); |
| } |
| |
| // Test that changing the framebuffer implicitly ends tiled rendering. |
| TEST_P(TiledRenderingTest, ImplicitEnd) |
| { |
| ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_tiled_rendering")); |
| |
| GLTexture tex1; |
| glBindTexture(GL_TEXTURE_2D, tex1); |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); |
| |
| GLFramebuffer fbo1; |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo1); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0); |
| |
| GLTexture tex2; |
| glBindTexture(GL_TEXTURE_2D, tex2); |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); |
| |
| GLFramebuffer fbo2; |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo2); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0); |
| |
| ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue()); |
| |
| glClearColor(0, 0, 0, 0); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo1); |
| glClear(GL_COLOR_BUFFER_BIT); |
| glStartTilingQCOM(0, 0, 8, 8, GL_COLOR_BUFFER_BIT0_QCOM); |
| EXPECT_GL_NO_ERROR(); |
| |
| drawQuad(program, essl1_shaders::PositionAttrib(), 0); |
| |
| // Switch framebuffer bindings. Tiling is implicitly ended and start can be called again without |
| // errors. |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo2); |
| glClear(GL_COLOR_BUFFER_BIT); |
| glStartTilingQCOM(8, 8, 8, 8, GL_COLOR_BUFFER_BIT0_QCOM); |
| EXPECT_GL_NO_ERROR(); |
| |
| drawQuad(program, essl1_shaders::PositionAttrib(), 0); |
| |
| glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); |
| |
| // Test that the correct tiling regions were used |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo1); |
| EXPECT_PIXEL_COLOR_EQ(4, 4, GLColor::blue); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo2); |
| EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::blue); |
| |
| // Qualcomm drivers do not implicitly end tiling when changing the texture bound to the |
| // framebuffer so ANGLE inherits this behaviour. Validate that tiling is not ended. |
| glBindTexture(GL_TEXTURE_2D, tex1); |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo1); |
| glClear(GL_COLOR_BUFFER_BIT); |
| glStartTilingQCOM(4, 4, 4, 4, GL_COLOR_BUFFER_BIT0_QCOM); |
| EXPECT_GL_NO_ERROR(); |
| |
| drawQuad(program, essl1_shaders::PositionAttrib(), 0); |
| |
| // Redefine to 8x8 with red data |
| std::vector<GLColor> redData(8 * 8, GLColor::red); |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, redData.data()); |
| |
| // If tiling is still continuing from before, should only draw to [4, 4] to (8, 8) |
| drawQuad(program, essl1_shaders::PositionAttrib(), 0); |
| |
| glStartTilingQCOM(4, 4, 4, 4, GL_COLOR_BUFFER_BIT0_QCOM); |
| EXPECT_GL_ERROR(GL_INVALID_OPERATION); |
| |
| glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); |
| EXPECT_GL_NO_ERROR(); |
| |
| EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::red); |
| EXPECT_PIXEL_RECT_EQ(4, 4, 4, 4, GLColor::blue); |
| } |
| |
| // Test that the only written areas are the intersection of scissor and tiled rendering area |
| TEST_P(TiledRenderingTest, Scissor) |
| { |
| ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_tiled_rendering")); |
| |
| ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue()); |
| |
| glClearColor(0, 0, 0, 0); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| glEnable(GL_SCISSOR_TEST); |
| glScissor(0, 0, 12, 12); |
| |
| glStartTilingQCOM(8, 8, 8, 8, GL_COLOR_BUFFER_BIT0_QCOM); |
| |
| // Scissor and tile intersect from [8, 8] to [12, 12] |
| |
| drawQuad(program, essl1_shaders::PositionAttrib(), 0); |
| |
| glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); |
| |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); |
| EXPECT_PIXEL_COLOR_EQ(6, 6, GLColor::transparentBlack); |
| EXPECT_PIXEL_RECT_EQ(8, 8, 4, 4, GLColor::blue); |
| EXPECT_PIXEL_COLOR_EQ(14, 14, GLColor::transparentBlack); |
| EXPECT_PIXEL_COLOR_EQ(18, 18, GLColor::transparentBlack); |
| } |
| |
| ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(TiledRenderingTest); |
| |
| } // namespace angle |