blob: 89f9b55b32111637b57c556b183880f1176b8f7c [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.h"
#import <OpenGL/gl.h>
#include "flutter/fml/logging.h"
#include "flutter/fml/platform/darwin/cf_utils.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterBackingStore.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterBackingStoreData.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterFrameBufferProvider.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
#include "third_party/skia/include/utils/mac/SkCGUtils.h"
namespace flutter {
FlutterGLCompositor::FlutterGLCompositor(FlutterViewController* view_controller,
NSOpenGLContext* opengl_context)
: FlutterCompositor(view_controller), open_gl_context_(opengl_context) {}
bool FlutterGLCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config,
FlutterBackingStore* backing_store_out) {
if (!view_controller_) {
return false;
}
CGSize size = CGSizeMake(config->size.width, config->size.height);
if (GetFrameStatus() != FrameStatus::kStarted) {
StartFrame();
// If the backing store is for the first layer, return the fbo for the
// FlutterView.
FlutterOpenGLRenderBackingStore* backingStore =
reinterpret_cast<FlutterOpenGLRenderBackingStore*>(
[view_controller_.flutterView backingStoreForSize:size]);
backing_store_out->open_gl.framebuffer.name = backingStore.frameBufferID;
} else {
FlutterFrameBufferProvider* fb_provider =
[[FlutterFrameBufferProvider alloc] initWithOpenGLContext:open_gl_context_];
FlutterIOSurfaceHolder* io_surface_holder = [FlutterIOSurfaceHolder alloc];
GLuint fbo = [fb_provider glFrameBufferId];
GLuint texture = [fb_provider glTextureId];
[io_surface_holder bindSurfaceToTexture:texture fbo:fbo size:size];
FlutterBackingStoreData* data =
[[FlutterBackingStoreData alloc] initWithFbProvider:fb_provider
ioSurfaceHolder:io_surface_holder];
backing_store_out->open_gl.framebuffer.name = fbo;
backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)data;
}
backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
backing_store_out->open_gl.framebuffer.target = GL_RGBA8;
backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) {
if (user_data != nullptr) {
// This deletes the OpenGL framebuffer object and texture backing it.
CFRelease(user_data);
}
};
return true;
}
bool FlutterGLCompositor::CollectBackingStore(const FlutterBackingStore* backing_store) {
return true;
}
bool FlutterGLCompositor::Present(const FlutterLayer** layers, size_t layers_count) {
SetFrameStatus(FrameStatus::kPresenting);
for (size_t i = 0; i < layers_count; ++i) {
const auto* layer = layers[i];
FlutterBackingStore* backing_store = const_cast<FlutterBackingStore*>(layer->backing_store);
switch (layer->type) {
case kFlutterLayerContentTypeBackingStore: {
if (backing_store->open_gl.framebuffer.user_data) {
FlutterBackingStoreData* backing_store_data =
(__bridge FlutterBackingStoreData*)backing_store->open_gl.framebuffer.user_data;
FlutterIOSurfaceHolder* io_surface_holder = [backing_store_data ioSurfaceHolder];
IOSurfaceRef io_surface = [io_surface_holder ioSurface];
// The surface is an OpenGL texture, which means it has origin in bottom left corner
// and needs to be flipped vertically
InsertCALayerForIOSurface(io_surface, CATransform3DMakeScale(1, -1, 1));
}
break;
}
case kFlutterLayerContentTypePlatformView:
// Add functionality in follow up PR.
FML_LOG(WARNING) << "Presenting PlatformViews not yet supported";
break;
};
}
return EndFrame();
}
} // namespace flutter