|
| 1 | +// Copyright 2013 The Flutter Authors. All rights reserved. |
| 2 | +// Use of this source code is governed by a BSD-style license that can be |
| 3 | +// found in the LICENSE file. |
| 4 | + |
| 5 | +#include <memory> |
| 6 | +#include "flutter/testing/testing.h" // IWYU pragma: keep |
| 7 | +#include "gmock/gmock.h" |
| 8 | +#include "gtest/gtest.h" |
| 9 | +#include "impeller/core/formats.h" |
| 10 | +#include "impeller/renderer/backend/gles/command_buffer_gles.h" |
| 11 | +#include "impeller/renderer/backend/gles/context_gles.h" |
| 12 | +#include "impeller/renderer/backend/gles/proc_table_gles.h" |
| 13 | +#include "impeller/renderer/backend/gles/reactor_gles.h" |
| 14 | +#include "impeller/renderer/backend/gles/test/mock_gles.h" |
| 15 | +#include "impeller/renderer/backend/gles/texture_gles.h" |
| 16 | +#include "impeller/renderer/context.h" |
| 17 | +#include "impeller/renderer/render_pass.h" |
| 18 | +#include "impeller/renderer/render_target.h" |
| 19 | + |
| 20 | +namespace impeller { |
| 21 | +namespace testing { |
| 22 | + |
| 23 | +using ::testing::_; |
| 24 | +using ::testing::Args; |
| 25 | +using ::testing::ElementsAreArray; |
| 26 | +using ::testing::NiceMock; |
| 27 | +using ::testing::Return; |
| 28 | +using ::testing::SetArgPointee; |
| 29 | +using ::testing::TestWithParam; |
| 30 | + |
| 31 | +class TestReactorGLES : public ReactorGLES { |
| 32 | + public: |
| 33 | + TestReactorGLES() |
| 34 | + : ReactorGLES(std::make_unique<ProcTableGLES>(kMockResolverGLES)) {} |
| 35 | + |
| 36 | + ~TestReactorGLES() = default; |
| 37 | +}; |
| 38 | + |
| 39 | +class MockWorker final : public ReactorGLES::Worker { |
| 40 | + public: |
| 41 | + MockWorker() = default; |
| 42 | + |
| 43 | + // |ReactorGLES::Worker| |
| 44 | + bool CanReactorReactOnCurrentThreadNow( |
| 45 | + const ReactorGLES& reactor) const override { |
| 46 | + return true; |
| 47 | + } |
| 48 | +}; |
| 49 | + |
| 50 | +struct DiscardFrameBufferParams { |
| 51 | + GLuint frame_buffer_id; |
| 52 | + std::array<GLenum, 3> expected_attachments; |
| 53 | +}; |
| 54 | + |
| 55 | +class RenderPassGLESWithDiscardFrameBufferExtTest |
| 56 | + : public TestWithParam<DiscardFrameBufferParams> {}; |
| 57 | + |
| 58 | +namespace { |
| 59 | +std::shared_ptr<ContextGLES> CreateFakeGLESContext() { |
| 60 | + auto dummy_gl_procs = std::make_unique<ProcTableGLES>(kMockResolverGLES); |
| 61 | + auto dummy_shader_library = std::vector<std::shared_ptr<fml::Mapping>>{}; |
| 62 | + auto flags = Flags{}; |
| 63 | + return ContextGLES::Create(flags, std::move(dummy_gl_procs), |
| 64 | + dummy_shader_library, false); |
| 65 | +} |
| 66 | +} // namespace |
| 67 | + |
| 68 | +TEST_P(RenderPassGLESWithDiscardFrameBufferExtTest, DiscardFramebufferExt) { |
| 69 | + auto mock_gl_impl = std::make_unique<NiceMock<MockGLESImpl>>(); |
| 70 | + auto& mock_gl_impl_ref = *mock_gl_impl; |
| 71 | + auto mock_gl = |
| 72 | + MockGLES::Init(std::move(mock_gl_impl), {{"GL_EXT_discard_framebuffer"}}); |
| 73 | + |
| 74 | + auto context = CreateFakeGLESContext(); |
| 75 | + auto dummy_worker = std::make_shared<MockWorker>(); |
| 76 | + context->AddReactorWorker(dummy_worker); |
| 77 | + auto reactor = context->GetReactor(); |
| 78 | + |
| 79 | + const auto command_buffer = |
| 80 | + std::static_pointer_cast<Context>(context)->CreateCommandBuffer(); |
| 81 | + auto render_target = RenderTarget{}; |
| 82 | + const auto description = TextureDescriptor{ |
| 83 | + .format = PixelFormat::kR8G8B8A8UNormInt, .size = {10, 10}}; |
| 84 | + |
| 85 | + const auto& test_params = GetParam(); |
| 86 | + auto framebuffer_texture = |
| 87 | + TextureGLES::WrapFBO(reactor, description, test_params.frame_buffer_id); |
| 88 | + |
| 89 | + auto color_attachment = ColorAttachment{Attachment{ |
| 90 | + .texture = framebuffer_texture, .store_action = StoreAction::kDontCare}}; |
| 91 | + render_target.SetColorAttachment(color_attachment, 0); |
| 92 | + const auto render_pass = command_buffer->CreateRenderPass(render_target); |
| 93 | + |
| 94 | + EXPECT_CALL(mock_gl_impl_ref, GetIntegerv(GL_FRAMEBUFFER_BINDING, _)) |
| 95 | + .WillOnce(SetArgPointee<1>(test_params.frame_buffer_id)); |
| 96 | + |
| 97 | + EXPECT_CALL(mock_gl_impl_ref, DiscardFramebufferEXT(GL_FRAMEBUFFER, _, _)) |
| 98 | + .With(Args<2, 1>(ElementsAreArray(test_params.expected_attachments))) |
| 99 | + .Times(1); |
| 100 | + ASSERT_TRUE(render_pass->EncodeCommands()); |
| 101 | + ASSERT_TRUE(reactor->React()); |
| 102 | +} |
| 103 | + |
| 104 | +INSTANTIATE_TEST_SUITE_P( |
| 105 | + FrameBufferObject, |
| 106 | + RenderPassGLESWithDiscardFrameBufferExtTest, |
| 107 | + ::testing::ValuesIn(std::vector<DiscardFrameBufferParams>{ |
| 108 | + {.frame_buffer_id = 0, |
| 109 | + .expected_attachments = {GL_COLOR_EXT, GL_DEPTH_EXT, GL_STENCIL_EXT}}, |
| 110 | + {.frame_buffer_id = 1, |
| 111 | + .expected_attachments = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, |
| 112 | + GL_STENCIL_ATTACHMENT}}}), |
| 113 | + [](const ::testing::TestParamInfo<DiscardFrameBufferParams>& info) { |
| 114 | + return (info.param.frame_buffer_id == 0) ? "Default" : "NonDefault"; |
| 115 | + }); |
| 116 | + |
| 117 | +} // namespace testing |
| 118 | +} // namespace impeller |
0 commit comments