blob: 9a657f290f4970dbec00fb7c885d1f11fa3078d5 [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.
#include "flutter/shell/platform/linux/fl_renderer_gl.h"
#include "flutter/shell/platform/linux/fl_backing_store_provider.h"
#include "flutter/shell/platform/linux/fl_view_private.h"
struct _FlRendererGL {
FlRenderer parent_instance;
};
G_DEFINE_TYPE(FlRendererGL, fl_renderer_gl, fl_renderer_get_type())
// Implements FlRenderer::create_contexts.
static gboolean fl_renderer_gl_create_contexts(FlRenderer* renderer,
GtkWidget* widget,
GdkGLContext** visible,
GdkGLContext** resource,
GError** error) {
GdkWindow* window = gtk_widget_get_parent_window(widget);
*visible = gdk_window_create_gl_context(window, error);
if (*error != nullptr)
return FALSE;
*resource = gdk_window_create_gl_context(window, error);
if (*error != nullptr)
return FALSE;
return TRUE;
}
// Implements FlRenderer::create_backing_store.
static gboolean fl_renderer_gl_create_backing_store(
FlRenderer* renderer,
const FlutterBackingStoreConfig* config,
FlutterBackingStore* backing_store_out) {
g_autoptr(GError) error = nullptr;
gboolean result = fl_renderer_make_current(renderer, &error);
if (!result) {
g_warning("Failed to make renderer current when creating backing store: %s",
error->message);
return FALSE;
}
FlBackingStoreProvider* provider =
fl_backing_store_provider_new(config->size.width, config->size.height);
if (!provider) {
g_warning("Failed to create backing store");
return FALSE;
}
uint32_t name = fl_backing_store_provider_get_gl_framebuffer_id(provider);
uint32_t format = fl_backing_store_provider_get_gl_format(provider);
backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
backing_store_out->open_gl.framebuffer.user_data = provider;
backing_store_out->open_gl.framebuffer.name = name;
backing_store_out->open_gl.framebuffer.target = format;
backing_store_out->open_gl.framebuffer.destruction_callback = [](void* p) {
// Backing store destroyed in fl_renderer_gl_collect_backing_store(), set
// on FlutterCompositor.collect_backing_store_callback during engine start.
};
return TRUE;
}
// Implements FlRenderer::collect_backing_store.
static gboolean fl_renderer_gl_collect_backing_store(
FlRenderer* renderer,
const FlutterBackingStore* backing_store) {
g_autoptr(GError) error = nullptr;
gboolean result = fl_renderer_make_current(renderer, &error);
if (!result) {
g_warning(
"Failed to make renderer current when collecting backing store: %s",
error->message);
return FALSE;
}
// OpenGL context is required when destroying #FlBackingStoreProvider.
g_object_unref(backing_store->open_gl.framebuffer.user_data);
return TRUE;
}
// Implements FlRenderer::present_layers.
static gboolean fl_renderer_gl_present_layers(FlRenderer* renderer,
const FlutterLayer** layers,
size_t layers_count) {
FlView* view = fl_renderer_get_view(renderer);
GdkGLContext* context = fl_renderer_get_context(renderer);
if (!view || !context)
return FALSE;
fl_view_begin_frame(view);
for (size_t i = 0; i < layers_count; ++i) {
const FlutterLayer* layer = layers[i];
switch (layer->type) {
case kFlutterLayerContentTypeBackingStore: {
const FlutterBackingStore* backing_store = layer->backing_store;
auto framebuffer = &backing_store->open_gl.framebuffer;
g_object_ref(context);
fl_view_add_gl_area(
view, context,
reinterpret_cast<FlBackingStoreProvider*>(framebuffer->user_data));
} break;
case kFlutterLayerContentTypePlatformView: {
// Currently unsupported.
} break;
}
}
fl_view_end_frame(view);
return TRUE;
}
static void fl_renderer_gl_class_init(FlRendererGLClass* klass) {
FL_RENDERER_CLASS(klass)->create_contexts = fl_renderer_gl_create_contexts;
FL_RENDERER_CLASS(klass)->create_backing_store =
fl_renderer_gl_create_backing_store;
FL_RENDERER_CLASS(klass)->collect_backing_store =
fl_renderer_gl_collect_backing_store;
FL_RENDERER_CLASS(klass)->present_layers = fl_renderer_gl_present_layers;
}
static void fl_renderer_gl_init(FlRendererGL* self) {}
FlRendererGL* fl_renderer_gl_new() {
return FL_RENDERER_GL(g_object_new(fl_renderer_gl_get_type(), nullptr));
}