Browse Source

[plugin] Add embedder_texture plugin for linux

embedder_texture
Vitaliy Zarubin 1 year ago
parent
commit
80e1758cc8
  1. 22
      example/lib/packages/embedder_texture/model.dart
  2. 25
      example/lib/packages/embedder_texture/package.dart
  3. 50
      example/lib/packages/embedder_texture/page.dart
  4. 2
      example/lib/packages/packages.dart
  5. 2
      example/linux/CMakeLists.txt
  6. 4
      example/linux/flutter/generated_plugin_registrant.cc
  7. 1
      example/linux/flutter/generated_plugins.cmake
  8. 4
      example/pubspec.yaml
  9. 30
      packages/embedder_texture/.gitignore
  10. 1
      packages/embedder_texture/analysis_options.yaml
  11. 54
      packages/embedder_texture/lib/embedder_texture.dart
  12. 27
      packages/embedder_texture/lib/embedder_texture_method_channel.dart
  13. 33
      packages/embedder_texture/lib/embedder_texture_platform_interface.dart
  14. 31
      packages/embedder_texture/linux/CMakeLists.txt
  15. 198
      packages/embedder_texture/linux/embedder_texture_plugin.cc
  16. 7
      packages/embedder_texture/linux/embedder_texture_plugin_private.h
  17. 44
      packages/embedder_texture/linux/fl_my_texture_gl.cc
  18. 26
      packages/embedder_texture/linux/include/embedder_texture/embedder_texture_plugin.h
  19. 28
      packages/embedder_texture/linux/include/fl_my_texture_gl.h
  20. 23
      packages/embedder_texture/pubspec.yaml

22
example/lib/packages/embedder_texture/model.dart

@ -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;
}

25
example/lib/packages/embedder_texture/package.dart

@ -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());
},
);

50
example/lib/packages/embedder_texture/page.dart

@ -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,
),
),
);
},
);
}
}

2
example/lib/packages/packages.dart

@ -34,9 +34,11 @@ import 'package:flutter_example_packages/packages/sqflite/package.dart';
import 'package:flutter_example_packages/packages/universal_io/package.dart';
import 'package:flutter_example_packages/packages/wakelock_plus/package.dart';
import 'package:flutter_example_packages/packages/xdga_directories/package.dart';
import 'package:flutter_example_packages/packages/embedder_texture/package.dart';
/// List app packages
final packages = <Package>[
packageEmbedderTexture,
packageBatteryPlus,
packageBuildRunner,
packageCachedNetworkImage,

2
example/linux/CMakeLists.txt

@ -41,7 +41,7 @@ endif()
# of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
# target_compile_options(${TARGET} PRIVATE -Wall -Werror)
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction()

4
example/linux/flutter/generated_plugin_registrant.cc

@ -6,9 +6,13 @@
#include "generated_plugin_registrant.h"
#include <embedder_texture/embedder_texture_plugin.h>
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) embedder_texture_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "EmbedderTexturePlugin");
embedder_texture_plugin_register_with_registrar(embedder_texture_registrar);
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);

1
example/linux/flutter/generated_plugins.cmake

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
embedder_texture
flutter_secure_storage_linux
)

4
example/pubspec.yaml

@ -163,6 +163,10 @@ dependencies:
# ref: master
# path: packages/wakelock_plus/wakelock_plus_aurora
## Test embedder texture plugin
embedder_texture:
path: ../packages/embedder_texture
dev_dependencies:
flutter_test:
sdk:

30
packages/embedder_texture/.gitignore vendored

@ -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/

1
packages/embedder_texture/analysis_options.yaml

@ -0,0 +1 @@
include: package:flutter_lints/flutter.yaml

54
packages/embedder_texture/lib/embedder_texture.dart

@ -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();
}
}

27
packages/embedder_texture/lib/embedder_texture_method_channel.dart

@ -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,
});
}
}

33
packages/embedder_texture/lib/embedder_texture_platform_interface.dart

@ -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.');
}
}

31
packages/embedder_texture/linux/CMakeLists.txt

@ -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
)

198
packages/embedder_texture/linux/embedder_texture_plugin.cc

@ -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);
}

7
packages/embedder_texture/linux/embedder_texture_plugin_private.h

@ -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);

44
packages/embedder_texture/linux/fl_my_texture_gl.cc

@ -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)
{
}

26
packages/embedder_texture/linux/include/embedder_texture/embedder_texture_plugin.h

@ -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_

28
packages/embedder_texture/linux/include/fl_my_texture_gl.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

23
packages/embedder_texture/pubspec.yaml

@ -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…
Cancel
Save