[047/906] * sys/glsink/gltestsrc.c: * sys/glsink/gstglbuffer.c: * sys/glsink/gstglbuf...
[platform/upstream/gstreamer.git] / gst-libs / gst / gl / gstglbuffer.c
1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5
6 #include <gstglbuffer.h>
7 #include <gstgldisplay.h>
8 #include <GL/glext.h>
9 #include <unistd.h>
10 #include "glextensions.h"
11
12 #include <string.h>
13
14 static GObjectClass *gst_gl_buffer_parent_class;
15
16 static void
17 gst_gl_buffer_finalize (GstGLBuffer * buffer)
18 {
19   gst_gl_display_lock (buffer->display);
20
21   glDeleteTextures (1, &buffer->texture);
22   if (buffer->texture_u) {
23     glDeleteTextures (1, &buffer->texture_u);
24   }
25   if (buffer->texture_v) {
26     glDeleteTextures (1, &buffer->texture_v);
27   }
28
29   gst_gl_display_unlock (buffer->display);
30   g_object_unref (buffer->display);
31
32   GST_MINI_OBJECT_CLASS (gst_gl_buffer_parent_class)->
33       finalize (GST_MINI_OBJECT (buffer));
34 }
35
36 static void
37 gst_gl_buffer_init (GstGLBuffer * buffer, gpointer g_class)
38 {
39
40 }
41
42 static void
43 gst_gl_buffer_class_init (gpointer g_class, gpointer class_data)
44 {
45   GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
46
47   gst_gl_buffer_parent_class = g_type_class_peek_parent (g_class);
48
49   mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
50       gst_gl_buffer_finalize;
51 }
52
53
54 GType
55 gst_gl_buffer_get_type (void)
56 {
57   static GType _gst_gl_buffer_type;
58
59   if (G_UNLIKELY (_gst_gl_buffer_type == 0)) {
60     static const GTypeInfo info = {
61       sizeof (GstBufferClass),
62       NULL,
63       NULL,
64       gst_gl_buffer_class_init,
65       NULL,
66       NULL,
67       sizeof (GstGLBuffer),
68       0,
69       (GInstanceInitFunc) gst_gl_buffer_init,
70       NULL
71     };
72     _gst_gl_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
73         "GstGLBuffer", &info, 0);
74   }
75   return _gst_gl_buffer_type;
76 }
77
78
79 GstGLBuffer *
80 gst_gl_buffer_new (GstGLDisplay * display, GstGLBufferFormat format,
81     int width, int height)
82 {
83   GstGLBuffer *buffer;
84
85   g_return_val_if_fail (width > 0, NULL);
86   g_return_val_if_fail (height > 0, NULL);
87
88   buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
89
90   buffer->display = g_object_ref (display);
91   buffer->width = width;
92   buffer->height = height;
93   /* this is not strictly true, but it's used for compatibility with
94    * queue and BaseTransform */
95   GST_BUFFER_SIZE (buffer) = width * height * 4;
96
97   gst_gl_display_lock (buffer->display);
98   glGenTextures (1, &buffer->texture);
99   glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture);
100   switch (format) {
101     case GST_GL_BUFFER_FORMAT_RGBA:
102       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
103           buffer->width, buffer->height, 0, GL_RGBA, GL_FLOAT, NULL);
104       break;
105     case GST_GL_BUFFER_FORMAT_RGB:
106       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
107           buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
108       break;
109     default:
110       g_warning ("GL buffer format not handled");
111   }
112
113   gst_gl_display_unlock (buffer->display);
114
115   return buffer;
116 }
117
118 GstGLBuffer *
119 gst_gl_buffer_new_from_data (GstGLDisplay * display, GstVideoFormat format,
120     int width, int height, void *data)
121 {
122   GstGLBuffer *buffer;
123   int comp;
124
125   g_return_val_if_fail (width > 0, NULL);
126   g_return_val_if_fail (height > 0, NULL);
127   g_return_val_if_fail (data != NULL, NULL);
128
129   GST_DEBUG ("uploading %p %dx%d", data, width, height);
130
131   buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
132   buffer->display = g_object_ref (display);
133   buffer->width = width;
134   buffer->height = height;
135   /* this is not strictly true, but it's used for compatibility with
136    * queue and BaseTransform */
137   GST_BUFFER_SIZE (buffer) = width * height * 4;
138
139   gst_gl_display_lock (buffer->display);
140   glGenTextures (1, &buffer->texture);
141   glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture);
142
143   switch (format) {
144     case GST_VIDEO_FORMAT_RGBx:
145       buffer->format = GST_GL_BUFFER_FORMAT_RGB;
146       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
147           buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
148       glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
149           GL_RGBA, GL_UNSIGNED_BYTE, data);
150       break;
151     case GST_VIDEO_FORMAT_BGRx:
152       buffer->format = GST_GL_BUFFER_FORMAT_RGB;
153       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
154           buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
155       glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
156           GL_BGRA, GL_UNSIGNED_BYTE, data);
157       break;
158     case GST_VIDEO_FORMAT_xRGB:
159       buffer->format = GST_GL_BUFFER_FORMAT_RGB;
160       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
161           buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
162       glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
163           GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, data);
164       break;
165     case GST_VIDEO_FORMAT_xBGR:
166       buffer->format = GST_GL_BUFFER_FORMAT_RGB;
167       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
168           buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
169       glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
170           GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, data);
171       break;
172     case GST_VIDEO_FORMAT_YUY2:
173       buffer->format = GST_GL_BUFFER_FORMAT_YUYV;
174       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width, height,
175           0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, NULL);
176       glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
177           GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, data);
178       break;
179     case GST_VIDEO_FORMAT_UYVY:
180       buffer->format = GST_GL_BUFFER_FORMAT_YUYV;
181       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width, height,
182           0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, NULL);
183       glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
184           GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, data);
185       break;
186     case GST_VIDEO_FORMAT_AYUV:
187       buffer->format = GST_GL_BUFFER_FORMAT_RGB;
188       buffer->is_yuv = TRUE;
189       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
190           buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
191       glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
192           GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, data);
193       break;
194     case GST_VIDEO_FORMAT_I420:
195     case GST_VIDEO_FORMAT_YV12:
196       buffer->format = GST_GL_BUFFER_FORMAT_PLANAR420;
197       buffer->is_yuv = TRUE;
198       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
199           buffer->width, buffer->height,
200           0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
201       glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
202           GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
203
204       glGenTextures (1, &buffer->texture_u);
205       glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture_u);
206       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
207           GST_ROUND_UP_2 (buffer->width) / 2,
208           GST_ROUND_UP_2 (buffer->height) / 2,
209           0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
210       comp = (format == GST_VIDEO_FORMAT_I420) ? 1 : 2;
211       glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
212           GST_ROUND_UP_2 (buffer->width) / 2,
213           GST_ROUND_UP_2 (buffer->height) / 2,
214           GL_LUMINANCE, GL_UNSIGNED_BYTE,
215           (guint8 *) data +
216           gst_video_format_get_component_offset (format, comp, width, height));
217
218       glGenTextures (1, &buffer->texture_v);
219       glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture_v);
220       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
221           GST_ROUND_UP_2 (buffer->width) / 2,
222           GST_ROUND_UP_2 (buffer->height) / 2,
223           0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
224       comp = (format == GST_VIDEO_FORMAT_I420) ? 2 : 1;
225       glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
226           GST_ROUND_UP_2 (buffer->width) / 2,
227           GST_ROUND_UP_2 (buffer->height) / 2,
228           GL_LUMINANCE, GL_UNSIGNED_BYTE,
229           (guint8 *) data +
230           gst_video_format_get_component_offset (format, comp, width, height));
231       break;
232     default:
233       g_assert_not_reached ();
234   }
235
236   gst_gl_display_unlock (buffer->display);
237
238   return buffer;
239 }
240
241
242 void
243 gst_gl_buffer_download (GstGLBuffer * buffer, GstVideoFormat format, void *data)
244 {
245   GLuint fbo;
246
247   GST_DEBUG ("downloading");
248
249   gst_gl_display_lock (buffer->display);
250
251   glGenFramebuffersEXT (1, &fbo);
252   glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
253
254   glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
255       GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, buffer->texture, 0);
256
257   glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT);
258   glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
259
260   g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
261       GL_FRAMEBUFFER_COMPLETE_EXT);
262
263   /* we need a reset function */
264   glMatrixMode (GL_COLOR);
265   glLoadIdentity ();
266   glPixelTransferf (GL_POST_COLOR_MATRIX_RED_BIAS, 0);
267   glPixelTransferf (GL_POST_COLOR_MATRIX_GREEN_BIAS, 0);
268   glPixelTransferf (GL_POST_COLOR_MATRIX_BLUE_BIAS, 0);
269
270   switch (format) {
271     case GST_VIDEO_FORMAT_RGBx:
272       glReadPixels (0, 0, buffer->width, buffer->height, GL_RGBA,
273           GL_UNSIGNED_BYTE, data);
274       break;
275     case GST_VIDEO_FORMAT_BGRx:
276       glReadPixels (0, 0, buffer->width, buffer->height, GL_BGRA,
277           GL_UNSIGNED_BYTE, data);
278       break;
279     case GST_VIDEO_FORMAT_xBGR:
280       glReadPixels (0, 0, buffer->width, buffer->height, GL_RGBA,
281           GL_UNSIGNED_INT_8_8_8_8, data);
282       break;
283     case GST_VIDEO_FORMAT_xRGB:
284       glReadPixels (0, 0, buffer->width, buffer->height, GL_BGRA,
285           GL_UNSIGNED_INT_8_8_8_8, data);
286       break;
287     default:
288       g_assert_not_reached ();
289   }
290
291   glDeleteFramebuffersEXT (1, &fbo);
292
293   gst_gl_display_unlock (buffer->display);
294 }