|
26 | 26 | bool FlutterGLCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config,
|
27 | 27 | FlutterBackingStore* backing_store_out) {
|
28 | 28 | CGSize size = CGSizeMake(config->size.width, config->size.height);
|
29 |
| - FlutterBackingStoreData* data = |
30 |
| - [[FlutterBackingStoreData alloc] initWithIsRootView:config->is_root_view]; |
31 | 29 |
|
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; |
| 30 | + if (!frame_started_) { |
| 31 | + StartFrame(); |
| 32 | + // If the backing store is for the first layer, return the fbo for the |
| 33 | + // FlutterView. |
41 | 34 | auto fbo = [view_controller_.flutterView frameBufferIDForSize:size];
|
42 | 35 | backing_store_out->open_gl.framebuffer.name = fbo;
|
43 | 36 | } else {
|
44 |
| - FML_CHECK(false) << "Compositor only supports creating a backing store for the root view"; |
| 37 | + FlutterFrameBufferProvider* fb_provider = |
| 38 | + [[FlutterFrameBufferProvider alloc] initWithOpenGLContext:open_gl_context_]; |
| 39 | + FlutterIOSurfaceHolder* io_surface_holder = [FlutterIOSurfaceHolder alloc]; |
| 40 | + |
| 41 | + GLuint fbo = [fb_provider glFrameBufferId]; |
| 42 | + GLuint texture = [fb_provider glTextureId]; |
| 43 | + |
| 44 | + size_t layer_id = CreateCALayer(); |
| 45 | + |
| 46 | + [io_surface_holder bindSurfaceToTexture:texture fbo:fbo size:size]; |
| 47 | + FlutterBackingStoreData* data = |
| 48 | + [[FlutterBackingStoreData alloc] initWithLayerId:layer_id |
| 49 | + fbProvider:fb_provider |
| 50 | + ioSurfaceHolder:io_surface_holder]; |
| 51 | + |
| 52 | + backing_store_out->open_gl.framebuffer.name = fbo; |
| 53 | + backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)data; |
45 | 54 | }
|
46 | 55 |
|
47 |
| - backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)data; |
| 56 | + backing_store_out->type = kFlutterBackingStoreTypeOpenGL; |
| 57 | + backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer; |
| 58 | + backing_store_out->open_gl.framebuffer.target = GL_RGBA8; |
| 59 | + backing_store_out->is_cacheable = false; |
48 | 60 | backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) {
|
49 | 61 | if (user_data != nullptr) {
|
50 | 62 | CFRelease(user_data);
|
|
64 | 76 | FlutterBackingStore* backing_store = const_cast<FlutterBackingStore*>(layer->backing_store);
|
65 | 77 | switch (layer->type) {
|
66 | 78 | 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."; |
| 79 | + if (backing_store->open_gl.framebuffer.user_data) { |
| 80 | + FlutterBackingStoreData* backing_store_data = |
| 81 | + (__bridge FlutterBackingStoreData*)backing_store->open_gl.framebuffer.user_data; |
| 82 | + |
| 83 | + FlutterIOSurfaceHolder* io_surface_holder = [backing_store_data getIOSurfaceHolder]; |
| 84 | + size_t layer_id = [backing_store_data getLayerId]; |
| 85 | + |
| 86 | + CALayer* content_layer = ca_layer_map_[layer_id]; |
| 87 | + content_layer.frame = CGRectMake(0, 0, layer->size.width, layer->size.height); |
| 88 | + content_layer.transform = CATransform3DMakeScale(1, -1, 1); |
| 89 | + IOSurfaceRef io_surface_contents = [io_surface_holder ioSurface]; |
| 90 | + [content_layer setContents:(__bridge id)io_surface_contents]; |
71 | 91 | }
|
72 | 92 | break;
|
73 | 93 | }
|
74 | 94 | case kFlutterLayerContentTypePlatformView:
|
75 | 95 | // Add functionality in follow up PR.
|
76 |
| - FML_CHECK(false) << "Presenting PlatformViews not yet supported"; |
| 96 | + FML_LOG(WARNING) << "Presenting PlatformViews not yet supported"; |
77 | 97 | break;
|
78 | 98 | };
|
79 | 99 | }
|
| 100 | + // The frame has been presented, prepare FlutterGLCompositor to |
| 101 | + // render a new frame. |
| 102 | + frame_started_ = false; |
80 | 103 | return present_callback_();
|
81 | 104 | }
|
82 | 105 |
|
|
85 | 108 | present_callback_ = present_callback;
|
86 | 109 | }
|
87 | 110 |
|
| 111 | +void FlutterGLCompositor::StartFrame() { |
| 112 | + // First reset all the state. |
| 113 | + ca_layer_count_ = 0; |
| 114 | + |
| 115 | + // First remove all CALayers from the superlayer. |
| 116 | + for (auto const& x : ca_layer_map_) { |
| 117 | + [x.second removeFromSuperlayer]; |
| 118 | + } |
| 119 | + |
| 120 | + // Reset layer map. |
| 121 | + ca_layer_map_.clear(); |
| 122 | + |
| 123 | + frame_started_ = true; |
| 124 | +} |
| 125 | + |
| 126 | +size_t FlutterGLCompositor::CreateCALayer() { |
| 127 | + // FlutterGLCompositor manages the lifecycle of content layers. |
| 128 | + // The id for a CALayer starts at 0 and increments by 1 for |
| 129 | + // any given frame. |
| 130 | + CALayer* content_layer = [[CALayer alloc] init]; |
| 131 | + [view_controller_.flutterView.layer addSublayer:content_layer]; |
| 132 | + ca_layer_map_[ca_layer_count_] = content_layer; |
| 133 | + return ca_layer_count_++; |
| 134 | +} |
| 135 | + |
88 | 136 | } // namespace flutter
|
0 commit comments