Flutter Windows Embedder
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 
9 
10 namespace flutter {
11 
12 constexpr int kOpaqueBlack = 0xff000000;
13 
14 namespace {
15 
16 /// Calculate the minimum and maximum x and y coordinates to enclose all layers.
17 FlutterRect CalculateBounds(const FlutterLayer** layers, size_t layers_count) {
18  double x_min = HUGE_VAL;
19  double x_max = -HUGE_VAL;
20  double y_min = HUGE_VAL;
21  double y_max = -HUGE_VAL;
22  for (const FlutterLayer** layer = layers; layer < layers + layers_count;
23  layer++) {
24  const FlutterPoint& offset = (*layer)->offset;
25  const FlutterSize& size = (*layer)->size;
26  x_min = std::min(x_min, offset.x);
27  y_min = std::min(y_min, offset.y);
28  x_max = std::max(x_max, offset.x + size.width);
29  y_max = std::max(y_max, offset.y + size.height);
30  }
31  return FlutterRect{x_min, y_min, x_max, y_max};
32 }
33 
34 /// Blend layer in-place onto allocation, which already holds the previous
35 /// results of composition.
36 void BlendLayer(std::vector<uint32_t>& allocation,
37  const FlutterLayer& layer,
38  int x_min,
39  int y_min,
40  int width,
41  int height) {
42  FML_DCHECK(layer.type == kFlutterLayerContentTypeBackingStore);
43  auto& backing_store = *layer.backing_store;
44  FML_DCHECK(backing_store.type == kFlutterBackingStoreTypeSoftware);
45  auto src_data =
46  static_cast<const uint32_t*>(backing_store.software.allocation);
47  const FlutterPoint& offset = layer.offset;
48  const FlutterSize& size = layer.size;
49 
50  // Bounds for iteration to prevent out-of-bounds destination coordinates.
51  int y_src_min = std::max(0., y_min - offset.y);
52  int y_src_max = std::min(size.height, height + y_min - offset.y);
53  int x_src_min = std::max(0., x_min - offset.x);
54  int x_src_max = std::min(size.width, width + x_min - offset.x);
55  for (int y_src = y_src_min; y_src < y_src_max; y_src++) {
56  int y_dst = y_src + offset.y - y_min;
57  for (int x_src = x_src_min; x_src < x_src_max; x_src++) {
58  int x_dst = x_src + offset.x + x_min;
59  size_t i_src = y_src * size.width + x_src;
60  size_t i_dst = y_dst * width + x_dst;
61  uint32_t src = src_data[i_src];
62  uint32_t dst = allocation[i_dst];
63 
64  int r_src = (src >> 0) & 0xff;
65  int g_src = (src >> 8) & 0xff;
66  int b_src = (src >> 16) & 0xff;
67  int a_src = (src >> 24) & 0xff;
68 
69  int r_dst = (dst >> 0) & 0xff;
70  int g_dst = (dst >> 8) & 0xff;
71  int b_dst = (dst >> 16) & 0xff;
72 
73  int r = (r_dst * 255 + (r_src - r_dst) * a_src) / 255;
74  int g = (g_dst * 255 + (g_src - g_dst) * a_src) / 255;
75  int b = (b_dst * 255 + (b_src - b_dst) * a_src) / 255;
76 
77  allocation[i_dst] = (r << 0) | (g << 8) | (b << 16) | (0xff << 24);
78  }
79  }
80 }
81 
82 } // namespace
83 
85 
87  const FlutterBackingStoreConfig& config,
88  FlutterBackingStore* result) {
89  size_t size = config.size.width * config.size.height * 4;
90  void* allocation = std::calloc(size, sizeof(uint8_t));
91  if (!allocation) {
92  return false;
93  }
94 
95  result->type = kFlutterBackingStoreTypeSoftware;
96  result->software.allocation = allocation;
97  result->software.height = config.size.height;
98  result->software.row_bytes = config.size.width * 4;
99  result->software.user_data = nullptr;
100  result->software.destruction_callback = [](void* user_data) {
101  // Backing store destroyed in `CompositorSoftware::CollectBackingStore`, set
102  // on FlutterCompositor.collect_backing_store_callback during engine start.
103  };
104  return true;
105 }
106 
107 bool CompositorSoftware::CollectBackingStore(const FlutterBackingStore* store) {
108  std::free(const_cast<void*>(store->software.allocation));
109  return true;
110 }
111 
113  const FlutterLayer** layers,
114  size_t layers_count) {
115  FML_DCHECK(view != nullptr);
116 
117  // Clear the view if there are no layers to present.
118  if (layers_count == 0) {
119  return view->ClearSoftwareBitmap();
120  }
121 
122  // Bypass composition logic if there is only one layer.
123  if (layers_count == 1) {
124  const FlutterLayer* layer = layers[0];
125  FML_DCHECK(layer != nullptr);
126  if (layer->type == kFlutterLayerContentTypeBackingStore &&
127  layer->offset.x == 0 && layer->offset.y == 0) {
128  auto& backing_store = *layer->backing_store;
129  FML_DCHECK(backing_store.type == kFlutterBackingStoreTypeSoftware);
130  auto& software = backing_store.software;
131  return view->PresentSoftwareBitmap(software.allocation,
132  software.row_bytes, software.height);
133  }
134  }
135 
136  // Composite many layers.
137  FlutterRect bounds = CalculateBounds(layers, layers_count);
138  // Truncate from double to integer to represent whole pixels.
139  int x_min = static_cast<int>(bounds.left);
140  int x_max = static_cast<int>(bounds.right);
141  int y_min = static_cast<int>(bounds.top);
142  int y_max = static_cast<int>(bounds.bottom);
143 
144  int width = x_max - x_min;
145  int height = y_max - y_min;
146  std::vector<uint32_t> allocation(width * height, kOpaqueBlack);
147 
148  for (const FlutterLayer** layer = layers; layer < layers + layers_count;
149  layer++) {
150  // TODO(schectman): handle platform view type layers.
151  // https://github.com/flutter/flutter/issues/143375
152  if ((*layer)->type == kFlutterLayerContentTypeBackingStore) {
153  BlendLayer(allocation, **layer, x_min, y_min, width, height);
154  } else {
155  FML_UNREACHABLE();
156  return false;
157  }
158  }
159 
160  return view->PresentSoftwareBitmap(static_cast<void*>(allocation.data()),
161  width * sizeof(uint32_t), height);
162 }
163 
164 } // namespace flutter
flutter::FlutterWindowsView
Definition: flutter_windows_view.h:34
flutter::CompositorSoftware::Present
bool Present(FlutterWindowsView *view, const FlutterLayer **layers, size_t layers_count) override
|Compositor|
Definition: compositor_software.cc:112
user_data
void * user_data
Definition: flutter_windows_view_unittests.cc:53
flutter::CompositorSoftware::CreateBackingStore
bool CreateBackingStore(const FlutterBackingStoreConfig &config, FlutterBackingStore *result) override
|Compositor|
Definition: compositor_software.cc:86
flutter_windows_view.h
flutter
Definition: accessibility_bridge_windows.cc:11
compositor_software.h
flutter::FlutterWindowsView::PresentSoftwareBitmap
virtual bool PresentSoftwareBitmap(const void *allocation, size_t row_bytes, size_t height)
Definition: flutter_windows_view.cc:682
flutter_windows_engine.h
flutter::FlutterWindowsView::ClearSoftwareBitmap
virtual bool ClearSoftwareBitmap()
Definition: flutter_windows_view.cc:678
flutter::CompositorSoftware::CompositorSoftware
CompositorSoftware()
Definition: compositor_software.cc:84
flutter::CompositorSoftware::CollectBackingStore
bool CollectBackingStore(const FlutterBackingStore *store) override
|Compositor|
Definition: compositor_software.cc:107
flutter::kOpaqueBlack
constexpr int kOpaqueBlack
Definition: compositor_software.cc:12