Flutter Linux Embedder
fl_compositor_software_test.cc
Go to the documentation of this file.
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 <thread>
6 #include "flutter/shell/platform/linux/testing/linux_test.h"
7 #include "gtest/gtest.h"
8 
9 #include "flutter/common/constants.h"
10 #include "flutter/fml/synchronization/waitable_event.h"
14 
15 #include <gdk/gdkwayland.h>
16 
17 class FlCompositorSoftwareTest : public flutter::testing::LinuxTest {
18  protected:
19  void SetUp() override {
22  }
23 
25  g_clear_object(&compositor);
26  g_clear_object(&task_runner);
27  }
28 
29  FlTaskRunner* task_runner = nullptr;
30  FlCompositorSoftware* compositor = nullptr;
31 };
32 
34  // Present layer from a thread.
35  constexpr size_t width = 100;
36  constexpr size_t height = 100;
37  size_t row_bytes = width * 4;
38  g_autofree unsigned char* layer_data =
39  static_cast<unsigned char*>(malloc(height * row_bytes));
40  FlutterBackingStore backing_store = {
41  .type = kFlutterBackingStoreTypeSoftware,
42  .software = {
43  .allocation = layer_data, .row_bytes = row_bytes, .height = height}};
44  FlutterLayer layer = {.type = kFlutterLayerContentTypeBackingStore,
45  .backing_store = &backing_store,
46  .offset = {0, 0},
47  .size = {width, height}};
48  const FlutterLayer* layers[1] = {&layer};
49  std::thread([&]() {
50  fl_compositor_present_layers(FL_COMPOSITOR(compositor), layers, 1);
51  }).join();
52 
53  size_t frame_width, frame_height;
54  fl_compositor_get_frame_size(FL_COMPOSITOR(compositor), &frame_width,
55  &frame_height);
56  EXPECT_EQ(frame_width, width);
57  EXPECT_EQ(frame_height, height);
58 
59  // Render presented layer.
60  int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
61  g_autofree unsigned char* image_data =
62  static_cast<unsigned char*>(malloc(height * stride));
63  cairo_surface_t* surface = cairo_image_surface_create_for_data(
64  image_data, CAIRO_FORMAT_ARGB32, width, height, stride);
65  cairo_t* cr = cairo_create(surface);
66  fl_compositor_render(FL_COMPOSITOR(compositor), cr, nullptr, TRUE);
67  cairo_surface_destroy(surface);
68  cairo_destroy(cr);
69 }
70 
72  // Present a layer that is the old size.
73  constexpr size_t width1 = 90;
74  constexpr size_t height1 = 90;
75  size_t row_bytes = width1 * 4;
76  g_autofree unsigned char* layer1_data =
77  static_cast<unsigned char*>(malloc(height1 * row_bytes));
78  FlutterBackingStore backing_store1 = {
79  .type = kFlutterBackingStoreTypeSoftware,
80  .software = {.allocation = layer1_data,
81  .row_bytes = row_bytes,
82  .height = height1}};
83  FlutterLayer layer1 = {.type = kFlutterLayerContentTypeBackingStore,
84  .backing_store = &backing_store1,
85  .offset = {0, 0},
86  .size = {width1, height1}};
87  const FlutterLayer* layers1[1] = {&layer1};
88  std::thread([&]() {
89  fl_compositor_present_layers(FL_COMPOSITOR(compositor), layers1, 1);
90  }).join();
91 
92  // Present layer in current size.
93  constexpr size_t width2 = 100;
94  constexpr size_t height2 = 100;
95  row_bytes = width2 * 4;
96  g_autofree unsigned char* layer2_data =
97  static_cast<unsigned char*>(malloc(height2 * row_bytes));
98  FlutterBackingStore backing_store2 = {
99  .type = kFlutterBackingStoreTypeSoftware,
100  .software = {.allocation = layer2_data,
101  .row_bytes = row_bytes,
102  .height = height2}};
103  FlutterLayer layer2 = {.type = kFlutterLayerContentTypeBackingStore,
104  .backing_store = &backing_store2,
105  .offset = {0, 0},
106  .size = {width2, height2}};
107  const FlutterLayer* layers2[1] = {&layer2};
108  fml::AutoResetWaitableEvent latch;
109  std::thread([&]() {
110  fl_compositor_present_layers(FL_COMPOSITOR(compositor), layers2, 1);
111  latch.Signal();
112  }).detach();
113 
114  // Render, will wait for the second layer if necessary.
115  int stride2 = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width2);
116  g_autofree unsigned char* image_data =
117  static_cast<unsigned char*>(malloc(height2 * stride2));
118  cairo_surface_t* surface = cairo_image_surface_create_for_data(
119  image_data, CAIRO_FORMAT_ARGB32, width2, height2, stride2);
120  cairo_t* cr = cairo_create(surface);
121  fl_compositor_render(FL_COMPOSITOR(compositor), cr, nullptr, TRUE);
122  cairo_surface_destroy(surface);
123  cairo_destroy(cr);
124 
125  latch.Wait();
126 }
gboolean fl_compositor_render(FlCompositor *self, cairo_t *cr, GdkWindow *window, gboolean wait_for_frame)
void fl_compositor_get_frame_size(FlCompositor *self, size_t *width, size_t *height)
gboolean fl_compositor_present_layers(FlCompositor *self, const FlutterLayer **layers, size_t layers_count)
FlFramebuffer double double int int height
FlFramebuffer double double int width
const FlutterLayer ** layers
return TRUE
FlCompositorSoftware * fl_compositor_software_new(FlTaskRunner *task_runner)
TEST_F(FlCompositorSoftwareTest, Render)
FlTaskRunner * fl_task_runner_new(FlEngine *engine)