Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
fl_compositor_software.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
6
8 FlCompositor parent_instance;
9
10 // Task runner to wait for frames on.
11 FlTaskRunner* task_runner;
12
13 // Width of frame in pixels.
14 size_t width;
15
16 // Height of frame in pixels.
17 size_t height;
18
19 // Surface to draw on view.
20 cairo_surface_t* surface;
21
22 // Ensure Flutter and GTK can access the surface.
24};
25
26G_DEFINE_TYPE(FlCompositorSoftware,
27 fl_compositor_software,
28 fl_compositor_get_type())
29
30static gboolean fl_compositor_software_present_layers(
31 FlCompositor* compositor,
33 size_t layers_count) {
34 FlCompositorSoftware* self = FL_COMPOSITOR_SOFTWARE(compositor);
35
36 g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->frame_mutex);
37
38 if (layers_count == 0) {
39 return TRUE;
40 }
41
42 self->width = layers[0]->size.width;
43 self->height = layers[0]->size.height;
44
45 // TODO(robert-ancell): Support multiple layers
46 if (layers_count == 1) {
47 const FlutterLayer* layer = layers[0];
50 const FlutterBackingStore* backing_store = layer->backing_store;
51
52 size_t allocation_length =
53 backing_store->software.row_bytes * backing_store->software.height;
54 unsigned char* old_data = self->surface != nullptr
55 ? cairo_image_surface_get_data(self->surface)
56 : nullptr;
57 unsigned char* data =
58 static_cast<unsigned char*>(g_realloc(old_data, allocation_length));
59 memcpy(data, backing_store->software.allocation, allocation_length);
60 cairo_surface_destroy(self->surface);
61 self->surface = cairo_image_surface_create_for_data(
62 data, CAIRO_FORMAT_ARGB32, backing_store->software.row_bytes / 4,
63 backing_store->software.height, backing_store->software.row_bytes);
64 }
65
67
68 return TRUE;
69}
70
71static void fl_compositor_software_get_frame_size(FlCompositor* compositor,
72 size_t* width,
73 size_t* height) {
74 FlCompositorSoftware* self = FL_COMPOSITOR_SOFTWARE(compositor);
75
76 g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->frame_mutex);
77
78 if (width != nullptr) {
79 *width = self->width;
80 }
81 if (height != nullptr) {
82 *height = self->height;
83 }
84}
85
86static gboolean fl_compositor_software_render(FlCompositor* compositor,
87 cairo_t* cr,
88 GdkWindow* window,
89 gboolean wait_for_frame) {
90 FlCompositorSoftware* self = FL_COMPOSITOR_SOFTWARE(compositor);
91
92 g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->frame_mutex);
93
94 if (self->surface == nullptr) {
95 return FALSE;
96 }
97
98 // If frame not ready, then wait for it.
99 gint scale_factor = gdk_window_get_scale_factor(window);
100 if (wait_for_frame) {
101 gint64 expiry_time =
102 g_get_monotonic_time() + kCompositorRenderTimeoutMicroseconds;
103 while (true) {
104 size_t width = gdk_window_get_width(window) * scale_factor;
105 size_t height = gdk_window_get_height(window) * scale_factor;
106 if (self->width == width && self->height == height) {
107 break;
108 }
109
110 if (g_get_monotonic_time() > expiry_time) {
111 g_warning(
112 "Timed out waiting for software frame of size %zdx%zd (have "
113 "%zdx%zd)",
114 width, height, self->width, self->height);
115 break;
116 }
117
118 g_mutex_unlock(&self->frame_mutex);
119 fl_task_runner_wait(self->task_runner, expiry_time);
120 g_mutex_lock(&self->frame_mutex);
121 }
122 }
123
124 cairo_surface_set_device_scale(self->surface, scale_factor, scale_factor);
125 cairo_set_source_surface(cr, self->surface, 0.0, 0.0);
126 cairo_paint(cr);
127
128 return TRUE;
129}
130
131static void fl_compositor_software_dispose(GObject* object) {
132 FlCompositorSoftware* self = FL_COMPOSITOR_SOFTWARE(object);
133
134 g_clear_object(&self->task_runner);
135 if (self->surface != nullptr) {
136 g_free(cairo_image_surface_get_data(self->surface));
137 }
138 g_clear_pointer(&self->surface, cairo_surface_destroy);
139 g_mutex_clear(&self->frame_mutex);
140
141 G_OBJECT_CLASS(fl_compositor_software_parent_class)->dispose(object);
142}
143
145 FlCompositorSoftwareClass* klass) {
146 FL_COMPOSITOR_CLASS(klass)->present_layers =
147 fl_compositor_software_present_layers;
148 FL_COMPOSITOR_CLASS(klass)->get_frame_size =
150 FL_COMPOSITOR_CLASS(klass)->render = fl_compositor_software_render;
151
152 G_OBJECT_CLASS(klass)->dispose = fl_compositor_software_dispose;
153}
154
155static void fl_compositor_software_init(FlCompositorSoftware* self) {
156 g_mutex_init(&self->frame_mutex);
157}
158
159FlCompositorSoftware* fl_compositor_software_new(FlTaskRunner* task_runner) {
160 FlCompositorSoftware* self = FL_COMPOSITOR_SOFTWARE(
161 g_object_new(fl_compositor_software_get_type(), nullptr));
162 self->task_runner = FL_TASK_RUNNER(g_object_ref(task_runner));
163 return self;
164}
@ kFlutterLayerContentTypeBackingStore
Definition embedder.h:2140
@ kFlutterBackingStoreTypeSoftware
Specified an software allocation for Flutter to render into using the CPU.
Definition embedder.h:2091
GLFWwindow * window
Definition main.cc:60
G_BEGIN_DECLS constexpr gint64 kCompositorRenderTimeoutMicroseconds
const FlutterLayer size_t layers_count
const FlutterLayer ** layers
FlCompositorSoftware * fl_compositor_software_new(FlTaskRunner *task_runner)
g_autoptr(GMutexLocker) locker
static void fl_compositor_software_class_init(FlCompositorSoftwareClass *klass)
return TRUE
G_DEFINE_TYPE(FlCompositorSoftware, fl_compositor_software, fl_compositor_get_type()) static gboolean fl_compositor_software_present_layers(FlCompositor *compositor
static void fl_compositor_software_init(FlCompositorSoftware *self)
fl_task_runner_stop_wait(self->task_runner)
static void fl_compositor_software_get_frame_size(FlCompositor *compositor, size_t *width, size_t *height)
static void fl_compositor_software_dispose(GObject *object)
static gboolean fl_compositor_software_render(FlCompositor *compositor, cairo_t *cr, GdkWindow *window, gboolean wait_for_frame)
void fl_task_runner_wait(FlTaskRunner *self, gint64 expiry_time)
int gdk_window_get_width(GdkWindow *window)
Definition mock_gtk.cc:75
gint gdk_window_get_scale_factor(GdkWindow *window)
Definition mock_gtk.cc:85
int gdk_window_get_height(GdkWindow *window)
Definition mock_gtk.cc:80
FlutterBackingStoreType type
Specifies the type of backing store.
Definition embedder.h:2109
FlutterSoftwareBackingStore software
The description of the software backing store.
Definition embedder.h:2117
FlutterLayerContentType type
Definition embedder.h:2172
const FlutterBackingStore * backing_store
Definition embedder.h:2176
FlutterSize size
The size of the layer (in physical pixels).
Definition embedder.h:2185
double height
Definition embedder.h:636
double width
Definition embedder.h:635
size_t row_bytes
The number of bytes in a single row of the allocation.
Definition embedder.h:1970
size_t height
The number of rows in the allocation.
Definition embedder.h:1972