|
3 | 3 | // found in the LICENSE file.
|
4 | 4 |
|
5 | 5 | #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.h"
|
6 |
| -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterBackingStoreData.h" |
7 |
| -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterFrameBufferProvider.h" |
8 |
| -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h" |
9 | 6 |
|
10 | 7 | #import <OpenGL/gl.h>
|
| 8 | + |
11 | 9 | #import "flutter/fml/logging.h"
|
12 | 10 | #import "flutter/fml/platform/darwin/cf_utils.h"
|
| 11 | +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterBackingStoreData.h" |
| 12 | +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterFrameBufferProvider.h" |
| 13 | +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h" |
13 | 14 | #import "third_party/skia/include/core/SkCanvas.h"
|
14 | 15 | #import "third_party/skia/include/core/SkSurface.h"
|
15 | 16 | #import "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
|
16 | 17 | #import "third_party/skia/include/utils/mac/SkCGUtils.h"
|
17 | 18 |
|
18 |
| -#include <unistd.h> |
19 |
| - |
20 | 19 | namespace flutter {
|
21 | 20 |
|
22 | 21 | FlutterGLCompositor::FlutterGLCompositor(FlutterViewController* view_controller)
|
|
26 | 25 | bool FlutterGLCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config,
|
27 | 26 | FlutterBackingStore* backing_store_out) {
|
28 | 27 | CGSize size = CGSizeMake(config->size.width, config->size.height);
|
29 |
| - FlutterBackingStoreData* data = |
30 |
| - [[FlutterBackingStoreData alloc] initWithIsRootView:config->is_root_view]; |
31 | 28 |
|
32 |
| - backing_store_out->type = kFlutterBackingStoreTypeOpenGL; |
33 |
| - backing_store_out->is_cacheable = true; |
34 |
| - backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer; |
35 |
| - backing_store_out->open_gl.framebuffer.target = GL_RGBA8; |
36 |
| - |
37 |
| - if (config->is_root_view) { |
38 |
| - // The root view uses FlutterSurfaceManager and is not cacheable since |
39 |
| - // the fbo id changes on every present. |
40 |
| - backing_store_out->is_cacheable = false; |
| 29 | + if (!frame_started_) { |
| 30 | + StartFrame(); |
| 31 | + // If the backing store is for the first layer, return the fbo for the |
| 32 | + // FlutterView. |
41 | 33 | auto fbo = [view_controller_.flutterView frameBufferIDForSize:size];
|
42 | 34 | backing_store_out->open_gl.framebuffer.name = fbo;
|
43 | 35 | } else {
|
44 |
| - FML_CHECK(false) << "Compositor only supports creating a backing store for the root view"; |
| 36 | + FlutterFrameBufferProvider* fb_provider = |
| 37 | + [[FlutterFrameBufferProvider alloc] initWithOpenGLContext:open_gl_context_]; |
| 38 | + FlutterIOSurfaceHolder* io_surface_holder = [FlutterIOSurfaceHolder alloc]; |
| 39 | + |
| 40 | + GLuint fbo = [fb_provider glFrameBufferId]; |
| 41 | + GLuint texture = [fb_provider glTextureId]; |
| 42 | + |
| 43 | + size_t layer_id = CreateCALayer(); |
| 44 | + |
| 45 | + [io_surface_holder bindSurfaceToTexture:texture fbo:fbo size:size]; |
| 46 | + FlutterBackingStoreData* data = |
| 47 | + [[FlutterBackingStoreData alloc] initWithLayerId:layer_id |
| 48 | + fbProvider:fb_provider |
| 49 | + ioSurfaceHolder:io_surface_holder]; |
| 50 | + |
| 51 | + backing_store_out->open_gl.framebuffer.name = fbo; |
| 52 | + backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)data; |
45 | 53 | }
|
46 | 54 |
|
47 |
| - backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)data; |
| 55 | + backing_store_out->type = kFlutterBackingStoreTypeOpenGL; |
| 56 | + backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer; |
| 57 | + backing_store_out->open_gl.framebuffer.target = GL_RGBA8; |
48 | 58 | backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) {
|
49 | 59 | if (user_data != nullptr) {
|
50 | 60 | CFRelease(user_data);
|
|
64 | 74 | FlutterBackingStore* backing_store = const_cast<FlutterBackingStore*>(layer->backing_store);
|
65 | 75 | switch (layer->type) {
|
66 | 76 | case kFlutterLayerContentTypeBackingStore: {
|
67 |
| - FlutterBackingStoreData* data = |
68 |
| - (__bridge FlutterBackingStoreData*)(backing_store->open_gl.framebuffer.user_data); |
69 |
| - if (![data isRootView]) { |
70 |
| - FML_CHECK(false) << "Compositor only supports presenting the root view."; |
| 77 | + if (backing_store->open_gl.framebuffer.user_data) { |
| 78 | + FlutterBackingStoreData* backing_store_data = |
| 79 | + (__bridge FlutterBackingStoreData*)backing_store->open_gl.framebuffer.user_data; |
| 80 | + |
| 81 | + FlutterIOSurfaceHolder* io_surface_holder = [backing_store_data ioSurfaceHolder]; |
| 82 | + size_t layer_id = [backing_store_data layerId]; |
| 83 | + |
| 84 | + CALayer* content_layer = ca_layer_map_[layer_id]; |
| 85 | + |
| 86 | + FML_CHECK(content_layer) << "Unable to find a content layer with layer id " << layer_id; |
| 87 | + |
| 88 | + content_layer.frame = content_layer.superlayer.bounds; |
| 89 | + content_layer.transform = CATransform3DMakeScale(1, -1, 1); |
| 90 | + IOSurfaceRef io_surface_contents = [io_surface_holder ioSurface]; |
| 91 | + [content_layer setContents:(__bridge id)io_surface_contents]; |
71 | 92 | }
|
72 | 93 | break;
|
73 | 94 | }
|
74 | 95 | case kFlutterLayerContentTypePlatformView:
|
75 | 96 | // Add functionality in follow up PR.
|
76 |
| - FML_CHECK(false) << "Presenting PlatformViews not yet supported"; |
| 97 | + FML_LOG(WARNING) << "Presenting PlatformViews not yet supported"; |
77 | 98 | break;
|
78 | 99 | };
|
79 | 100 | }
|
| 101 | + // The frame has been presented, prepare FlutterGLCompositor to |
| 102 | + // render a new frame. |
| 103 | + frame_started_ = false; |
80 | 104 | return present_callback_();
|
81 | 105 | }
|
82 | 106 |
|
|
85 | 109 | present_callback_ = present_callback;
|
86 | 110 | }
|
87 | 111 |
|
| 112 | +void FlutterGLCompositor::StartFrame() { |
| 113 | + // First reset all the state. |
| 114 | + ca_layer_count_ = 0; |
| 115 | + |
| 116 | + // First remove all CALayers from the superlayer. |
| 117 | + for (auto const& x : ca_layer_map_) { |
| 118 | + [x.second removeFromSuperlayer]; |
| 119 | + } |
| 120 | + |
| 121 | + // Reset layer map. |
| 122 | + ca_layer_map_.clear(); |
| 123 | + |
| 124 | + frame_started_ = true; |
| 125 | +} |
| 126 | + |
| 127 | +size_t FlutterGLCompositor::CreateCALayer() { |
| 128 | + // FlutterGLCompositor manages the lifecycle of content layers. |
| 129 | + // The id for a CALayer starts at 0 and increments by 1 for |
| 130 | + // any given frame. |
| 131 | + CALayer* content_layer = [[CALayer alloc] init]; |
| 132 | + [view_controller_.flutterView.layer addSublayer:content_layer]; |
| 133 | + ca_layer_map_[ca_layer_count_] = content_layer; |
| 134 | + return ca_layer_count_++; |
| 135 | +} |
| 136 | + |
88 | 137 | } // namespace flutter
|
0 commit comments