1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #include "flutter/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h" |
6 | |
7 | #include <epoxy/gl.h> |
8 | #include <gmodule.h> |
9 | |
10 | #include "flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h" |
11 | |
12 | typedef struct { |
13 | int64_t id; |
14 | GLuint texture_id; |
15 | } FlPixelBufferTexturePrivate; |
16 | |
17 | static void fl_pixel_buffer_texture_iface_init(FlTextureInterface* iface); |
18 | |
19 | G_DEFINE_TYPE_WITH_CODE( |
20 | FlPixelBufferTexture, |
21 | fl_pixel_buffer_texture, |
22 | G_TYPE_OBJECT, |
23 | G_IMPLEMENT_INTERFACE(fl_texture_get_type(), |
24 | fl_pixel_buffer_texture_iface_init); |
25 | G_ADD_PRIVATE(FlPixelBufferTexture)) |
26 | |
27 | // Implements FlTexture::set_id |
28 | static void fl_pixel_buffer_texture_set_id(FlTexture* texture, int64_t id) { |
29 | FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(texture); |
30 | FlPixelBufferTexturePrivate* priv = |
31 | reinterpret_cast<FlPixelBufferTexturePrivate*>( |
32 | fl_pixel_buffer_texture_get_instance_private(self)); |
33 | priv->id = id; |
34 | } |
35 | |
36 | // Implements FlTexture::set_id |
37 | static int64_t fl_pixel_buffer_texture_get_id(FlTexture* texture) { |
38 | FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(texture); |
39 | FlPixelBufferTexturePrivate* priv = |
40 | reinterpret_cast<FlPixelBufferTexturePrivate*>( |
41 | fl_pixel_buffer_texture_get_instance_private(self)); |
42 | return priv->id; |
43 | } |
44 | |
45 | static void fl_pixel_buffer_texture_iface_init(FlTextureInterface* iface) { |
46 | iface->set_id = fl_pixel_buffer_texture_set_id; |
47 | iface->get_id = fl_pixel_buffer_texture_get_id; |
48 | } |
49 | |
50 | static void fl_pixel_buffer_texture_dispose(GObject* object) { |
51 | FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(object); |
52 | FlPixelBufferTexturePrivate* priv = |
53 | reinterpret_cast<FlPixelBufferTexturePrivate*>( |
54 | fl_pixel_buffer_texture_get_instance_private(self)); |
55 | |
56 | if (priv->texture_id) { |
57 | glDeleteTextures(1, &priv->texture_id); |
58 | priv->texture_id = 0; |
59 | } |
60 | |
61 | G_OBJECT_CLASS(fl_pixel_buffer_texture_parent_class)->dispose(object); |
62 | } |
63 | |
64 | static void check_gl_error(int line) { |
65 | GLenum err = glGetError(); |
66 | if (err) { |
67 | g_warning("glGetError %x (%s:%d)\n" , err, __FILE__, line); |
68 | } |
69 | } |
70 | |
71 | gboolean fl_pixel_buffer_texture_populate(FlPixelBufferTexture* texture, |
72 | uint32_t width, |
73 | uint32_t height, |
74 | FlutterOpenGLTexture* opengl_texture, |
75 | GError** error) { |
76 | FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(texture); |
77 | FlPixelBufferTexturePrivate* priv = |
78 | reinterpret_cast<FlPixelBufferTexturePrivate*>( |
79 | fl_pixel_buffer_texture_get_instance_private(self)); |
80 | |
81 | const uint8_t* buffer = nullptr; |
82 | if (!FL_PIXEL_BUFFER_TEXTURE_GET_CLASS(self)->copy_pixels( |
83 | self, &buffer, &width, &height, error)) { |
84 | return FALSE; |
85 | } |
86 | |
87 | if (priv->texture_id == 0) { |
88 | glGenTextures(1, &priv->texture_id); |
89 | check_gl_error(__LINE__); |
90 | glBindTexture(GL_TEXTURE_2D, priv->texture_id); |
91 | check_gl_error(__LINE__); |
92 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); |
93 | check_gl_error(__LINE__); |
94 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); |
95 | check_gl_error(__LINE__); |
96 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
97 | check_gl_error(__LINE__); |
98 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
99 | check_gl_error(__LINE__); |
100 | } else { |
101 | glBindTexture(GL_TEXTURE_2D, priv->texture_id); |
102 | check_gl_error(__LINE__); |
103 | } |
104 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, |
105 | GL_UNSIGNED_BYTE, buffer); |
106 | check_gl_error(__LINE__); |
107 | |
108 | opengl_texture->target = GL_TEXTURE_2D; |
109 | opengl_texture->name = priv->texture_id; |
110 | opengl_texture->format = GL_RGBA8; |
111 | opengl_texture->destruction_callback = nullptr; |
112 | opengl_texture->user_data = nullptr; |
113 | opengl_texture->width = width; |
114 | opengl_texture->height = height; |
115 | |
116 | return TRUE; |
117 | } |
118 | |
119 | static void fl_pixel_buffer_texture_class_init( |
120 | FlPixelBufferTextureClass* klass) { |
121 | G_OBJECT_CLASS(klass)->dispose = fl_pixel_buffer_texture_dispose; |
122 | } |
123 | |
124 | static void fl_pixel_buffer_texture_init(FlPixelBufferTexture* self) {} |
125 | |