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