Vitaliy Zarubin
1 year ago
20 changed files with 611 additions and 1 deletions
@ -0,0 +1,22 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> |
||||
// SPDX-License-Identifier: BSD-3-Clause |
||||
import 'package:flutter/widgets.dart'; |
||||
import 'package:scoped_model/scoped_model.dart'; |
||||
import 'package:xdga_directories/xdga_directories.dart' as xdga; |
||||
|
||||
/// Model for [EmbedderTexturePage] |
||||
class EmbedderTextureModel extends Model { |
||||
/// Get [ScopedModel] |
||||
static EmbedderTextureModel of(BuildContext context) => |
||||
ScopedModel.of<EmbedderTextureModel>(context); |
||||
|
||||
/// Error |
||||
String? _error; |
||||
|
||||
/// Public error |
||||
String? get error => _error; |
||||
|
||||
/// Public is error |
||||
bool get isError => _error != null; |
||||
|
||||
} |
@ -0,0 +1,25 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> |
||||
// SPDX-License-Identifier: BSD-3-Clause |
||||
import 'package:flutter_example_packages/base/package/package_page.dart'; |
||||
import 'package:flutter_example_packages/packages/embedder_texture/page.dart'; |
||||
import 'package:get_it/get_it.dart'; |
||||
|
||||
import 'model.dart'; |
||||
|
||||
/// Package values |
||||
final packageEmbedderTexture = PackagePage( |
||||
key: 'Embedder Texture', |
||||
descEN: ''' |
||||
Test Embedder texture plugin |
||||
''', |
||||
descRU: ''' |
||||
Тестирование текстур Embedder |
||||
''', |
||||
version: '0.0.1', |
||||
isPlatformDependent: true, |
||||
page: () => EmbedderTexturePage(), |
||||
init: () { |
||||
GetIt.instance |
||||
.registerFactory<EmbedderTextureModel>(() => EmbedderTextureModel()); |
||||
}, |
||||
); |
@ -0,0 +1,50 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> |
||||
// SPDX-License-Identifier: BSD-3-Clause |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_example_packages/base/di/app_di.dart'; |
||||
import 'package:flutter_example_packages/base/package/package.dart'; |
||||
import 'package:flutter_example_packages/packages/embedder_texture/model.dart'; |
||||
import 'package:flutter_example_packages/packages/embedder_texture/package.dart'; |
||||
import 'package:flutter_example_packages/widgets/base/export.dart'; |
||||
import 'package:flutter_example_packages/widgets/blocks/block_alert.dart'; |
||||
import 'package:flutter_example_packages/widgets/blocks/block_info_package.dart'; |
||||
import 'package:flutter_example_packages/widgets/blocks/block_item.dart'; |
||||
import 'package:flutter_example_packages/widgets/layouts/block_layout.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
import 'package:embedder_texture/embedder_texture.dart'; |
||||
|
||||
class EmbedderTexturePage extends AppStatefulWidget { |
||||
EmbedderTexturePage({ |
||||
super.key, |
||||
}); |
||||
|
||||
final Package package = packageEmbedderTexture; |
||||
|
||||
@override |
||||
State<EmbedderTexturePage> createState() => _EmbedderTexturePageState(); |
||||
} |
||||
|
||||
class _EmbedderTexturePageState extends AppState<EmbedderTexturePage> { |
||||
@override |
||||
Widget buildWide( |
||||
BuildContext context, |
||||
MediaQueryData media, |
||||
AppLocalizations l10n, |
||||
) { |
||||
return BlockLayout<EmbedderTextureModel>( |
||||
model: getIt<EmbedderTextureModel>(), |
||||
title: widget.package.key, |
||||
builder: (context, child, model) { |
||||
return const Padding( |
||||
padding: EdgeInsets.all(20), |
||||
child: Center( |
||||
child: EmbedderTexture( |
||||
width: 320, |
||||
height: 320, |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,30 @@
|
||||
# Miscellaneous |
||||
*.class |
||||
*.log |
||||
*.pyc |
||||
*.swp |
||||
.DS_Store |
||||
.atom/ |
||||
.buildlog/ |
||||
.history |
||||
.svn/ |
||||
migrate_working_dir/ |
||||
|
||||
# IntelliJ related |
||||
*.iml |
||||
*.ipr |
||||
*.iws |
||||
.idea/ |
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in |
||||
# VS Code which you may wish to be included in version control, so this line |
||||
# is commented out by default. |
||||
.vscode/ |
||||
|
||||
# Flutter/Dart/Pub related |
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. |
||||
/pubspec.lock |
||||
**/doc/api/ |
||||
.dart_tool/ |
||||
.packages |
||||
build/ |
@ -0,0 +1 @@
|
||||
include: package:flutter_lints/flutter.yaml |
@ -0,0 +1,54 @@
|
||||
|
||||
import 'package:flutter/material.dart'; |
||||
|
||||
import 'embedder_texture_platform_interface.dart'; |
||||
|
||||
class EmbedderTexture extends StatefulWidget { |
||||
const EmbedderTexture({ |
||||
super.key, |
||||
required this.width, |
||||
required this.height, |
||||
}); |
||||
|
||||
final double width; |
||||
final double height; |
||||
|
||||
@override |
||||
State<EmbedderTexture> createState() => _EmbedderTextureState(); |
||||
} |
||||
|
||||
class _EmbedderTextureState extends State<EmbedderTexture> { |
||||
int _textureID = 0; |
||||
|
||||
@override |
||||
initState() { |
||||
super.initState(); |
||||
EmbedderTexturePlatform.instance |
||||
.create(widget.width, widget.height) |
||||
.then((value) => setState(() { |
||||
if (mounted) { |
||||
_textureID = value!; |
||||
} |
||||
})); |
||||
} |
||||
|
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
EmbedderTexturePlatform.instance.remove(_textureID); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
if (_textureID != 0) { |
||||
return SizedBox( |
||||
width: widget.width, |
||||
height: widget.height, |
||||
child: Center( |
||||
child: Texture(textureId: _textureID) |
||||
), |
||||
); |
||||
} |
||||
return const SizedBox.shrink(); |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
import 'package:flutter/foundation.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
|
||||
import 'embedder_texture_platform_interface.dart'; |
||||
|
||||
/// An implementation of [LinuxOpenglPlatform] that uses method channels. |
||||
class MethodChannelEmbedderTexture extends EmbedderTexturePlatform { |
||||
/// The method channel used to interact with the native platform. |
||||
@visibleForTesting |
||||
final methodChannel = const MethodChannel('embedder_texture'); |
||||
|
||||
@override |
||||
Future<int?> create(double width, double height) async { |
||||
final version = await methodChannel.invokeMethod<int>('create', { |
||||
'width': width, |
||||
'height': height, |
||||
}); |
||||
return version; |
||||
} |
||||
|
||||
@override |
||||
Future<void> remove(int textureId) async { |
||||
await methodChannel.invokeMethod<int>('remove', { |
||||
'textureId': textureId, |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart'; |
||||
|
||||
import 'embedder_texture_method_channel.dart'; |
||||
|
||||
abstract class EmbedderTexturePlatform extends PlatformInterface { |
||||
/// Constructs a LinuxOpenglPlatform. |
||||
EmbedderTexturePlatform() : super(token: _token); |
||||
|
||||
static final Object _token = Object(); |
||||
|
||||
static EmbedderTexturePlatform _instance = MethodChannelEmbedderTexture(); |
||||
|
||||
/// The default instance of [LinuxOpenglPlatform] to use. |
||||
/// |
||||
/// Defaults to [MethodChannelLinuxOpengl]. |
||||
static EmbedderTexturePlatform get instance => _instance; |
||||
|
||||
/// Platform-specific implementations should set this with their own |
||||
/// platform-specific class that extends [LinuxOpenglPlatform] when |
||||
/// they register themselves. |
||||
static set instance(EmbedderTexturePlatform instance) { |
||||
PlatformInterface.verifyToken(instance, _token); |
||||
_instance = instance; |
||||
} |
||||
|
||||
Future<int?> create(double width, double height) { |
||||
throw UnimplementedError('create() has not been implemented.'); |
||||
} |
||||
|
||||
Future<void> remove(int textureId) { |
||||
throw UnimplementedError('remove() has not been implemented.'); |
||||
} |
||||
} |
@ -0,0 +1,31 @@
|
||||
cmake_minimum_required(VERSION 3.10) |
||||
|
||||
set(PROJECT_NAME "embedder_texture") |
||||
project(${PROJECT_NAME} LANGUAGES CXX) |
||||
|
||||
set(PLUGIN_NAME "embedder_texture_plugin") |
||||
|
||||
list(APPEND PLUGIN_SOURCES |
||||
"fl_my_texture_gl.cc" |
||||
"embedder_texture_plugin.cc" |
||||
) |
||||
|
||||
add_library(${PLUGIN_NAME} SHARED |
||||
${PLUGIN_SOURCES} |
||||
) |
||||
|
||||
apply_standard_settings(${PLUGIN_NAME}) |
||||
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) |
||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) |
||||
|
||||
target_include_directories(${PLUGIN_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include") |
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) |
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) |
||||
|
||||
# sudo apt-get install libglew-dev |
||||
target_link_libraries(${PLUGIN_NAME} PUBLIC |
||||
EGL |
||||
GLEW |
||||
GL |
||||
) |
@ -0,0 +1,198 @@
|
||||
#include "include/embedder_texture/embedder_texture_plugin.h" |
||||
#include "include/fl_my_texture_gl.h" |
||||
|
||||
#include <flutter_linux/flutter_linux.h> |
||||
#include <flutter_linux/fl_view.h> |
||||
#include <gtk/gtk.h> |
||||
#include <gdk/gdkx.h> |
||||
#include <sys/utsname.h> |
||||
#include <glib.h> |
||||
#include <GL/glew.h> |
||||
|
||||
#include <thread> |
||||
#include <chrono> |
||||
#include <vector> |
||||
|
||||
#include "embedder_texture_plugin_private.h" |
||||
|
||||
#define EMBEDDER_TEXTURE_PLUGIN(obj) \ |
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), embedder_texture_plugin_get_type(), \
|
||||
LinuxOpenglPlugin)) |
||||
|
||||
struct _LinuxOpenglPlugin |
||||
{ |
||||
GObject parent_instance; |
||||
|
||||
unsigned int width = 0; |
||||
unsigned int height = 0; |
||||
unsigned int texture_id = 0; |
||||
|
||||
FlTexture *texture = nullptr; |
||||
FlTextureRegistrar *texture_registrar = nullptr; |
||||
|
||||
GdkGLContext *context = nullptr; |
||||
GdkWindow *window = nullptr; |
||||
FlMyTextureGL *myTexture = nullptr; |
||||
FlView *fl_view = nullptr; |
||||
}; |
||||
|
||||
G_DEFINE_TYPE(LinuxOpenglPlugin, embedder_texture_plugin, g_object_get_type()) |
||||
|
||||
// Called when a method call is received from Flutter.
|
||||
static void embedder_texture_plugin_handle_method_call( |
||||
LinuxOpenglPlugin *self, |
||||
FlMethodCall *method_call) |
||||
{ |
||||
|
||||
g_autoptr(FlMethodResponse) response = nullptr; |
||||
|
||||
const gchar *method = fl_method_call_get_name(method_call); |
||||
|
||||
if (strcmp(method, "create") == 0) |
||||
{ |
||||
response = create(self, method_call); |
||||
} |
||||
else if (strcmp(method, "remove") == 0) |
||||
{ |
||||
response = remove(self, method_call); |
||||
} |
||||
else |
||||
{ |
||||
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); |
||||
} |
||||
|
||||
fl_method_call_respond(method_call, response, nullptr); |
||||
} |
||||
|
||||
void set_color(LinuxOpenglPlugin *self) |
||||
{ |
||||
gdk_gl_context_make_current(self->context); |
||||
|
||||
static GLfloat pixels[] = |
||||
{ |
||||
1, 0, 0, |
||||
0, 1, 0, |
||||
0, 0, 1, |
||||
1, 1, 1 |
||||
}; |
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_FLOAT, pixels); |
||||
|
||||
fl_texture_registrar_mark_texture_frame_available(self->texture_registrar, self->texture); |
||||
} |
||||
|
||||
FlMethodResponse *create( |
||||
LinuxOpenglPlugin *self, |
||||
FlMethodCall *method_call) |
||||
{ |
||||
GError *error = NULL; |
||||
FlValue *args = fl_method_call_get_args(method_call); |
||||
FlValue *w = fl_value_lookup_string(args, "width"); |
||||
FlValue *h = fl_value_lookup_string(args, "height"); |
||||
|
||||
if (w != nullptr) |
||||
{ |
||||
self->width = fl_value_get_float(w); |
||||
} |
||||
|
||||
if (h != nullptr) |
||||
{ |
||||
self->height = fl_value_get_float(h); |
||||
} |
||||
|
||||
if (self->width != 0 && self->height != 0) |
||||
{ |
||||
self->window = gtk_widget_get_parent_window(GTK_WIDGET(self->fl_view)); |
||||
self->context = gdk_window_create_gl_context(self->window, &error); |
||||
|
||||
gdk_gl_context_make_current(self->context); |
||||
|
||||
glGenTextures(1, &self->texture_id); |
||||
glBindTexture(GL_TEXTURE_2D, self->texture_id); |
||||
|
||||
// drawing on the texture
|
||||
set_color(self); |
||||
|
||||
self->myTexture = fl_my_texture_gl_new(GL_TEXTURE_2D, self->texture_id, self->width, self->height); |
||||
self->texture = FL_TEXTURE(self->myTexture); |
||||
|
||||
fl_texture_registrar_register_texture(self->texture_registrar, self->texture); |
||||
gdk_gl_context_clear_current(); |
||||
|
||||
g_autoptr(FlValue) result = fl_value_new_int(reinterpret_cast<int64_t>(self->texture)); |
||||
return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); |
||||
} |
||||
|
||||
return FL_METHOD_RESPONSE(fl_method_error_response_new( |
||||
"500", |
||||
"Method create() called without passing width or height parameters!", |
||||
nullptr)); |
||||
} |
||||
|
||||
FlMethodResponse *remove( |
||||
LinuxOpenglPlugin *self, |
||||
FlMethodCall *method_call) |
||||
{ |
||||
FlValue *args = fl_method_call_get_args(method_call); |
||||
FlValue *id = fl_value_lookup_string(args, "textureId"); |
||||
|
||||
if (id != nullptr) |
||||
{ |
||||
int textureId = fl_value_get_int(id); |
||||
fl_texture_registrar_unregister_texture(self->texture_registrar, self->texture); |
||||
g_autoptr(FlValue) result = fl_value_new_null(); |
||||
return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); |
||||
} |
||||
|
||||
return FL_METHOD_RESPONSE(fl_method_error_response_new( |
||||
"500", |
||||
"Method remove() called without passing textureId parameters!", |
||||
nullptr)); |
||||
} |
||||
|
||||
static void embedder_texture_plugin_dispose(GObject *object) |
||||
{ |
||||
G_OBJECT_CLASS(embedder_texture_plugin_parent_class)->dispose(object); |
||||
} |
||||
|
||||
static void embedder_texture_plugin_class_init(LinuxOpenglPluginClass *klass) |
||||
{ |
||||
G_OBJECT_CLASS(klass)->dispose = embedder_texture_plugin_dispose; |
||||
} |
||||
|
||||
static void embedder_texture_plugin_init(LinuxOpenglPlugin *self) {} |
||||
|
||||
static void method_call_cb(FlMethodChannel *channel, FlMethodCall *method_call, |
||||
gpointer user_data) |
||||
{ |
||||
LinuxOpenglPlugin *plugin = EMBEDDER_TEXTURE_PLUGIN(user_data); |
||||
embedder_texture_plugin_handle_method_call(plugin, method_call); |
||||
} |
||||
|
||||
void embedder_texture_plugin_register_with_registrar(FlPluginRegistrar *registrar) |
||||
{ |
||||
LinuxOpenglPlugin *plugin = EMBEDDER_TEXTURE_PLUGIN( |
||||
g_object_new(embedder_texture_plugin_get_type(), nullptr)); |
||||
|
||||
plugin->fl_view = fl_plugin_registrar_get_view(registrar); |
||||
plugin->texture_registrar = fl_plugin_registrar_get_texture_registrar(registrar); |
||||
|
||||
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); |
||||
g_autoptr(FlMethodChannel) channel = |
||||
fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar), |
||||
"embedder_texture", |
||||
FL_METHOD_CODEC(codec)); |
||||
fl_method_channel_set_method_call_handler(channel, method_call_cb, |
||||
g_object_ref(plugin), |
||||
g_object_unref); |
||||
|
||||
GLenum err = glewInit(); |
||||
if (GLEW_OK != err) |
||||
{ |
||||
printf("%s", "Error!"); |
||||
printf("%s", glewGetErrorString(err)); |
||||
return; |
||||
} |
||||
|
||||
g_object_unref(plugin); |
||||
} |
@ -0,0 +1,7 @@
|
||||
#include <flutter_linux/flutter_linux.h> |
||||
|
||||
#include "include/embedder_texture/embedder_texture_plugin.h" |
||||
|
||||
FlMethodResponse *create(LinuxOpenglPlugin *self, FlMethodCall *method_call); |
||||
|
||||
FlMethodResponse *remove(LinuxOpenglPlugin *self, FlMethodCall *method_call); |
@ -0,0 +1,44 @@
|
||||
#include "include/fl_my_texture_gl.h" |
||||
|
||||
G_DEFINE_TYPE(FlMyTextureGL, |
||||
fl_my_texture_gl, |
||||
fl_texture_gl_get_type()) |
||||
|
||||
static gboolean fl_my_texture_gl_populate(FlTextureGL *texture, |
||||
uint32_t *target, |
||||
uint32_t *name, |
||||
uint32_t *width, |
||||
uint32_t *height, |
||||
GError **error) |
||||
{ |
||||
FlMyTextureGL* f = (FlMyTextureGL*) texture; |
||||
*target = f->target; |
||||
*name = f->name; |
||||
*width = f->width; |
||||
*height = f->height; |
||||
return true; |
||||
} |
||||
|
||||
FlMyTextureGL *fl_my_texture_gl_new(uint32_t target, |
||||
uint32_t name, |
||||
uint32_t width, |
||||
uint32_t height) |
||||
{ |
||||
auto r = FL_MY_TEXTURE_GL(g_object_new(fl_my_texture_gl_get_type(), nullptr)); |
||||
r->target = target; |
||||
r->name = name; |
||||
r->width = width; |
||||
r->height = height; |
||||
return r; |
||||
} |
||||
|
||||
static void fl_my_texture_gl_class_init( |
||||
FlMyTextureGLClass *klass) |
||||
{ |
||||
FL_TEXTURE_GL_CLASS(klass)->populate = |
||||
fl_my_texture_gl_populate; |
||||
} |
||||
|
||||
static void fl_my_texture_gl_init(FlMyTextureGL *self) |
||||
{ |
||||
} |
@ -0,0 +1,26 @@
|
||||
#ifndef FLUTTER_PLUGIN_EMBEDDER_TEXTURE_PLUGIN_H_ |
||||
#define FLUTTER_PLUGIN_EMBEDDER_TEXTURE_PLUGIN_H_ |
||||
|
||||
#include <flutter_linux/flutter_linux.h> |
||||
|
||||
G_BEGIN_DECLS |
||||
|
||||
#ifdef FLUTTER_PLUGIN_IMPL |
||||
#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) |
||||
#else |
||||
#define FLUTTER_PLUGIN_EXPORT |
||||
#endif |
||||
|
||||
typedef struct _LinuxOpenglPlugin LinuxOpenglPlugin; |
||||
typedef struct { |
||||
GObjectClass parent_class; |
||||
} LinuxOpenglPluginClass; |
||||
|
||||
FLUTTER_PLUGIN_EXPORT GType embedder_texture_plugin_get_type(); |
||||
|
||||
FLUTTER_PLUGIN_EXPORT void embedder_texture_plugin_register_with_registrar( |
||||
FlPluginRegistrar* registrar); |
||||
|
||||
G_END_DECLS |
||||
|
||||
#endif // FLUTTER_PLUGIN_EMBEDDER_TEXTURE_PLUGIN_H_
|
@ -0,0 +1,28 @@
|
||||
#ifndef FLUTTER_MY_TEXTURE_H |
||||
#define FLUTTER_MY_TEXTURE_H |
||||
|
||||
#include <gtk/gtk.h> |
||||
#include <glib-object.h> |
||||
#include "embedder_texture/embedder_texture_plugin.h" |
||||
#include <flutter_linux/flutter_linux.h> |
||||
|
||||
G_DECLARE_FINAL_TYPE(FlMyTextureGL, |
||||
fl_my_texture_gl, |
||||
FL, |
||||
MY_TEXTURE_GL, |
||||
FlTextureGL) |
||||
|
||||
struct _FlMyTextureGL |
||||
{ |
||||
FlTextureGL parent_instance; |
||||
uint32_t target; |
||||
uint32_t name; |
||||
uint32_t width; |
||||
uint32_t height; |
||||
}; |
||||
|
||||
FlMyTextureGL *fl_my_texture_gl_new(uint32_t target, |
||||
uint32_t name, |
||||
uint32_t width, |
||||
uint32_t height); |
||||
#endif // FLUTTER_MY_TEXTURE_H
|
@ -0,0 +1,23 @@
|
||||
name: embedder_texture |
||||
description: Example create texture. |
||||
version: 0.0.1 |
||||
|
||||
environment: |
||||
sdk: '>=3.0.6 <4.0.0' |
||||
flutter: ">=3.3.0" |
||||
|
||||
dependencies: |
||||
flutter: |
||||
sdk: flutter |
||||
plugin_platform_interface: ^2.0.2 |
||||
|
||||
dev_dependencies: |
||||
flutter_test: |
||||
sdk: flutter |
||||
flutter_lints: ^2.0.0 |
||||
|
||||
flutter: |
||||
plugin: |
||||
platforms: |
||||
linux: |
||||
pluginClass: EmbedderTexturePlugin |
Loading…
Reference in new issue