Skip to content

Commit

Permalink
TestBasicScreenShooter: Test threading requirements.
Browse files Browse the repository at this point in the history
Because the `Renderer` hides thread-local state (in the form of an EGL context)
it's important that the `BasicScreenShooter` do the dance required to ensure
the `Renderer` tries to be current on at most one thread at a time.
  • Loading branch information
RAOF authored and AlanGriffiths committed Jul 17, 2023
1 parent afb75e0 commit c302751
Showing 1 changed file with 54 additions and 0 deletions.
54 changes: 54 additions & 0 deletions tests/unit-tests/compositor/test_basic_screen_shooter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "mir/executor.h"
#include "mir/graphics/platform.h"
#include "mir/renderer/gl/gl_surface.h"
#include "mir/test/doubles/stub_gl_rendering_provider.h"
Expand Down Expand Up @@ -233,3 +234,56 @@ TEST_F(BasicScreenShooter, throw_in_render_causes_graceful_failure)
EXPECT_CALL(callback, Call(nullopt_time));
executor.execute();
}

TEST_F(BasicScreenShooter, ensures_renderer_is_current_on_only_one_thread)
{
thread_local bool is_current_here = false;
std::atomic<bool> is_current = false;

auto shooter = std::make_unique<mc::BasicScreenShooter>(
scene,
clock,
mir::thread_pool_executor,
gl_providers,
renderer_factory);

ON_CALL(*next_renderer, render(_))
.WillByDefault(
[&](auto) -> std::unique_ptr<mg::Framebuffer>
{
/* It's OK if we're being made current again on the same thread
* without having been released previously.
* We just need to ensure that, if we are current *anywhere* then
* it's *this* thread that we're current on.
*/
EXPECT_THAT(is_current_here, Eq(is_current.load()));
is_current = true;
is_current_here = true;
return {};
});
ON_CALL(*next_renderer, suspend())
.WillByDefault(
[&]()
{
EXPECT_THAT(is_current_here, Eq(is_current.load()));
is_current = false;
is_current_here = false;
});

// This doesn't actually have to be atomic
std::atomic<int> call_count = 0;
auto const spawn_a_capture =
[&]()
{
shooter->capture(buffer, viewport_rect, [&](auto) { call_count++; });
};

auto const expected_call_count = 20;
for (auto i = 0; i < expected_call_count; ++i)
{
mir::thread_pool_executor.spawn(spawn_a_capture);
}

mir::ThreadPoolExecutor::quiesce();
EXPECT_THAT(call_count, Eq(expected_call_count));
}

0 comments on commit c302751

Please sign in to comment.