1 
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 #include <schroedinger/schrodebug.h>
6 #include <schroedinger/opengl/schroopengl.h>
7 #include <schroedinger/opengl/schroopenglcanvas.h>
8 #include <schroedinger/opengl/schroopenglframe.h>
9 #include <schroedinger/opengl/schroopenglshader.h>
10 #include <schroedinger/opengl/schroopenglwavelet.h>
11 #include <stdio.h>
12 
13 void
schro_opengl_frame_setup(SchroOpenGL * opengl,SchroFrame * frame)14 schro_opengl_frame_setup (SchroOpenGL *opengl, SchroFrame *frame)
15 {
16   int i;
17   int components;
18   int width, height;
19   SchroFrameFormat format;
20   SchroOpenGLCanvasPool *canvas_pool;
21   SchroOpenGLCanvas *canvas;
22 
23   SCHRO_ASSERT (frame != NULL);
24   SCHRO_ASSERT (SCHRO_FRAME_IS_OPENGL (frame));
25 
26   components = SCHRO_FRAME_IS_PACKED (frame->format) ? 1 : 3;
27 
28   schro_opengl_lock (opengl);
29 
30   canvas_pool = schro_opengl_get_canvas_pool (opengl);
31 
32   for (i = 0; i < components; ++i) {
33     format = frame->components[i].format;
34     width = frame->components[i].width;
35     height = frame->components[i].height;
36 
37     SCHRO_ASSERT (frame->format == format);
38 
39     canvas = schro_opengl_canvas_pool_pull_or_new (canvas_pool, opengl, format,
40         width, height);
41 
42     // FIXME: hack to store custom data per frame component
43     *((SchroOpenGLCanvas **) frame->components[i].data) = canvas;
44   }
45 
46   schro_opengl_unlock (opengl);
47 }
48 
49 void
schro_opengl_frame_cleanup(SchroFrame * frame)50 schro_opengl_frame_cleanup (SchroFrame *frame)
51 {
52   int i;
53   int components;
54   SchroOpenGL *opengl;
55   SchroOpenGLCanvasPool *canvas_pool;
56   SchroOpenGLCanvas *canvas;
57 
58   SCHRO_ASSERT (frame != NULL);
59   SCHRO_ASSERT (SCHRO_FRAME_IS_OPENGL (frame));
60 
61   components = SCHRO_FRAME_IS_PACKED (frame->format) ? 1 : 3;
62   // FIXME: hack to store custom data per frame component
63   canvas = *((SchroOpenGLCanvas **) frame->components[0].data);
64 
65   SCHRO_ASSERT (canvas != NULL);
66 
67   opengl = canvas->opengl;
68 
69   schro_opengl_lock (opengl);
70 
71   canvas_pool = schro_opengl_get_canvas_pool (opengl);
72 
73   for (i = 0; i < components; ++i) {
74     // FIXME: hack to store custom data per frame component
75     canvas = *((SchroOpenGLCanvas **) frame->components[i].data);
76 
77     SCHRO_ASSERT (canvas != NULL);
78     SCHRO_ASSERT (canvas->opengl == opengl);
79 
80     schro_opengl_canvas_pool_push_or_free (canvas_pool, canvas);
81   }
82 
83   schro_opengl_unlock (opengl);
84 }
85 
86 SchroFrame *
schro_opengl_frame_new(SchroOpenGL * opengl,SchroMemoryDomain * opengl_domain,SchroFrameFormat format,int width,int height)87 schro_opengl_frame_new (SchroOpenGL *opengl,
88     SchroMemoryDomain *opengl_domain, SchroFrameFormat format, int width,
89     int height)
90 {
91   SchroFrame *opengl_frame;
92 
93   SCHRO_ASSERT (opengl_domain->flags & SCHRO_MEMORY_DOMAIN_OPENGL);
94 
95   opengl_frame = schro_frame_new_and_alloc (opengl_domain, format, width,
96       height);
97 
98   schro_opengl_frame_setup (opengl, opengl_frame);
99 
100   return opengl_frame;
101 }
102 
103 SchroFrame *
schro_opengl_frame_clone(SchroFrame * opengl_frame)104 schro_opengl_frame_clone (SchroFrame *opengl_frame)
105 {
106   SchroOpenGLCanvas *canvas;
107 
108   SCHRO_ASSERT (opengl_frame != NULL);
109   SCHRO_ASSERT (SCHRO_FRAME_IS_OPENGL (opengl_frame));
110 
111   // FIXME: hack to store custom data per frame component
112   canvas = *((SchroOpenGLCanvas **) opengl_frame->components[0].data);
113 
114   SCHRO_ASSERT (canvas != NULL);
115 
116   return schro_opengl_frame_new (canvas->opengl, opengl_frame->domain,
117       opengl_frame->format, opengl_frame->width, opengl_frame->height);
118 }
119 
120 SchroFrame *
schro_opengl_frame_clone_and_push(SchroOpenGL * opengl,SchroMemoryDomain * opengl_domain,SchroFrame * cpu_frame)121 schro_opengl_frame_clone_and_push (SchroOpenGL *opengl,
122     SchroMemoryDomain *opengl_domain, SchroFrame *cpu_frame)
123 {
124   SchroFrame *opengl_frame;
125 
126   SCHRO_ASSERT (opengl_domain->flags & SCHRO_MEMORY_DOMAIN_OPENGL);
127   SCHRO_ASSERT (!SCHRO_FRAME_IS_OPENGL (cpu_frame));
128 
129   opengl_frame = schro_frame_clone (opengl_domain, cpu_frame);
130 
131   schro_opengl_frame_setup (opengl, opengl_frame);
132   schro_opengl_frame_push (opengl_frame, cpu_frame);
133 
134   return opengl_frame;
135 }
136 
137 void
schro_opengl_frame_inverse_iwt_transform(SchroFrame * frame,SchroParams * params)138 schro_opengl_frame_inverse_iwt_transform (SchroFrame *frame,
139     SchroParams *params)
140 {
141   int i;
142   int width, height;
143   int level;
144   SchroOpenGL *opengl;
145   SchroOpenGLCanvas *canvas;
146 
147   // FIXME: hack to store custom data per frame component
148   canvas = *((SchroOpenGLCanvas **) frame->components[0].data);
149 
150   SCHRO_ASSERT (canvas != NULL);
151 
152   opengl = canvas->opengl;
153 
154   schro_opengl_lock (opengl);
155 
156   for (i = 0; i < 3; ++i) {
157     // FIXME: hack to store custom data per frame component
158     canvas = *((SchroOpenGLCanvas **) frame->components[i].data);
159 
160     SCHRO_ASSERT (canvas != NULL);
161     SCHRO_ASSERT (canvas->opengl == opengl);
162 
163     if (i == 0) {
164       width = params->iwt_luma_width;
165       height = params->iwt_luma_height;
166     } else {
167       width = params->iwt_chroma_width;
168       height = params->iwt_chroma_height;
169     }
170 
171     for (level = params->transform_depth - 1; level >= 0; --level) {
172       SchroFrameData frame_data;
173 
174       frame_data.format = frame->format;
175       frame_data.data = frame->components[i].data;
176       frame_data.width = width >> level;
177       frame_data.height = height >> level;
178       frame_data.stride = frame->components[i].stride << level;
179 
180       schro_opengl_wavelet_inverse_transform (&frame_data,
181           params->wavelet_filter_index);
182     }
183   }
184 
185   schro_opengl_unlock (opengl);
186 }
187 
188 static void
schro_opengl_upsampled_frame_render_quad(SchroOpenGLShader * shader,int x,int y,int quad_width,int quad_height,int total_width,int total_height)189 schro_opengl_upsampled_frame_render_quad (SchroOpenGLShader *shader, int x,
190     int y, int quad_width, int quad_height, int total_width, int total_height)
191 {
192   int x_inverse, y_inverse;
193   int four_x = 0, four_y = 0, three_x = 0, three_y = 0, two_x = 0, two_y = 0,
194       one_x = 0, one_y = 0;
195 
196   x_inverse = total_width - x - quad_width;
197   y_inverse = total_height - y - quad_height;
198 
199   if (quad_width == total_width && quad_height < total_height) {
200     four_y = 4;
201     three_y = 3;
202     two_y = 2;
203     one_y = 1;
204   } else if (quad_width < total_width && quad_height == total_height) {
205     four_x = 4;
206     three_x = 3;
207     two_x = 2;
208     one_x = 1;
209   } else {
210     SCHRO_ERROR ("invalid quad to total relation");
211     SCHRO_ASSERT (0);
212   }
213 
214   SCHRO_ASSERT (x_inverse >= 0);
215   SCHRO_ASSERT (y_inverse >= 0);
216 
217   #define UNIFORM(_number, _operation, __x, __y) \
218       do { \
219         if (shader->_number##_##_operation != -1) { \
220           glUniform2fARB (shader->_number##_##_operation, \
221               __x < _number##_x ? __x : _number##_x, \
222               __y < _number##_y ? __y : _number##_y); \
223         } \
224       } while (0)
225 
226   UNIFORM (four, decrease, x, y);
227   UNIFORM (three, decrease, x, y);
228   UNIFORM (two, decrease, x, y);
229   UNIFORM (one, decrease, x, y);
230   UNIFORM (one, increase, x_inverse, y_inverse);
231   UNIFORM (two, increase, x_inverse, y_inverse);
232   UNIFORM (three, increase, x_inverse, y_inverse);
233   UNIFORM (four, increase, x_inverse, y_inverse);
234 
235   #undef UNIFORM
236 
237   schro_opengl_render_quad (x, y, quad_width, quad_height);
238 }
239 
240 void
schro_opengl_upsampled_frame_upsample(SchroUpsampledFrame * upsampled_frame)241 schro_opengl_upsampled_frame_upsample (SchroUpsampledFrame *upsampled_frame)
242 {
243   int i;
244   int width, height;
245   SchroOpenGLCanvas *canvases[4];
246   SchroOpenGL *opengl;
247   SchroOpenGLShader *shader = NULL;
248 
249   SCHRO_ASSERT (upsampled_frame->frames[0] != NULL);
250   SCHRO_ASSERT (upsampled_frame->frames[1] == NULL);
251   SCHRO_ASSERT (upsampled_frame->frames[2] == NULL);
252   SCHRO_ASSERT (upsampled_frame->frames[3] == NULL);
253   SCHRO_ASSERT (SCHRO_FRAME_IS_OPENGL (upsampled_frame->frames[0]));
254   SCHRO_ASSERT (!SCHRO_FRAME_IS_PACKED (upsampled_frame->frames[0]->format));
255 
256   // FIXME: hack to store custom data per frame component
257   canvases[0] = *((SchroOpenGLCanvas **) upsampled_frame->frames[0]->components[0].data);
258 
259   SCHRO_ASSERT (canvases[0] != NULL);
260 
261   opengl = canvases[0]->opengl;
262 
263   schro_opengl_lock (opengl);
264 
265   upsampled_frame->frames[1] = schro_opengl_frame_clone (upsampled_frame->frames[0]);
266   upsampled_frame->frames[2] = schro_opengl_frame_clone (upsampled_frame->frames[0]);
267   upsampled_frame->frames[3] = schro_opengl_frame_clone (upsampled_frame->frames[0]);
268 
269   shader = schro_opengl_shader_get (opengl, SCHRO_OPENGL_SHADER_UPSAMPLE_U8);
270 
271   SCHRO_ASSERT (shader != NULL);
272 
273   glUseProgramObjectARB (shader->program);
274   glUniform1iARB (shader->textures[0], 0);
275 
276   SCHRO_OPENGL_CHECK_ERROR
277 
278   for (i = 0; i < 3; ++i) {
279     // FIXME: hack to store custom data per frame component
280     canvases[0] = *((SchroOpenGLCanvas **) upsampled_frame->frames[0]->components[i].data);
281     canvases[1] = *((SchroOpenGLCanvas **) upsampled_frame->frames[1]->components[i].data);
282     canvases[2] = *((SchroOpenGLCanvas **) upsampled_frame->frames[2]->components[i].data);
283     canvases[3] = *((SchroOpenGLCanvas **) upsampled_frame->frames[3]->components[i].data);
284 
285     SCHRO_ASSERT (canvases[0] != NULL);
286     SCHRO_ASSERT (canvases[1] != NULL);
287     SCHRO_ASSERT (canvases[2] != NULL);
288     SCHRO_ASSERT (canvases[3] != NULL);
289     SCHRO_ASSERT (canvases[0]->opengl == opengl);
290     SCHRO_ASSERT (canvases[1]->opengl == opengl);
291     SCHRO_ASSERT (canvases[2]->opengl == opengl);
292     SCHRO_ASSERT (canvases[3]->opengl == opengl);
293 
294     width = upsampled_frame->frames[0]->components[i].width;
295     height = upsampled_frame->frames[0]->components[i].height;
296 
297     SCHRO_ASSERT (width >= 2);
298     SCHRO_ASSERT (height >= 2);
299     SCHRO_ASSERT (width % 2 == 0);
300     SCHRO_ASSERT (height % 2 == 0);
301 
302     schro_opengl_setup_viewport (width, height);
303 
304     /* horizontal filter 0 -> 1 */
305     glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, canvases[1]->framebuffers[0]);
306     glBindTexture (GL_TEXTURE_RECTANGLE_ARB, canvases[0]->texture.handles[0]);
307 
308     SCHRO_OPENGL_CHECK_ERROR
309 
310     #define RENDER_QUAD_HORIZONTAL(_x, _quad_width) \
311         schro_opengl_upsampled_frame_render_quad (shader, _x, 0,  _quad_width,\
312             height, width, height)
313 
314     RENDER_QUAD_HORIZONTAL (0, 1);
315 
316     if (width > 2) {
317       RENDER_QUAD_HORIZONTAL (1, 1);
318 
319       if (width > 4) {
320         RENDER_QUAD_HORIZONTAL (2, 1);
321 
322         if (width > 6) {
323           RENDER_QUAD_HORIZONTAL (3, 1);
324 
325            if (width > 8) {
326              RENDER_QUAD_HORIZONTAL (4, width - 8);
327            }
328 
329            RENDER_QUAD_HORIZONTAL (width - 4, 1);
330         }
331 
332         RENDER_QUAD_HORIZONTAL (width - 3, 1);
333       }
334 
335       RENDER_QUAD_HORIZONTAL (width - 2, 1);
336     }
337 
338     RENDER_QUAD_HORIZONTAL (width - 1, 1);
339 
340     #undef RENDER_QUAD_HORIZONTAL
341 
342     /* vertical filter 0 -> 2 */
343     glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, canvases[2]->framebuffers[0]);
344     glBindTexture (GL_TEXTURE_RECTANGLE_ARB, canvases[0]->texture.handles[0]);
345 
346     SCHRO_OPENGL_CHECK_ERROR
347 
348     #define RENDER_QUAD_VERTICAL(_y, _quad_height) \
349         schro_opengl_upsampled_frame_render_quad (shader, 0, _y,  width,\
350             _quad_height, width, height)
351 
352     RENDER_QUAD_VERTICAL (0, 1);
353 
354     if (height > 2) {
355       RENDER_QUAD_VERTICAL (1, 1);
356 
357       if (height > 4) {
358         RENDER_QUAD_VERTICAL (2, 1);
359 
360         if (height > 6) {
361           RENDER_QUAD_VERTICAL (3, 1);
362 
363            if (height > 8) {
364              RENDER_QUAD_VERTICAL (4, height - 8);
365            }
366 
367            RENDER_QUAD_VERTICAL (height - 4, 1);
368         }
369 
370         RENDER_QUAD_VERTICAL (height - 3, 1);
371       }
372 
373       RENDER_QUAD_VERTICAL (height - 2, 1);
374     }
375 
376     RENDER_QUAD_VERTICAL (height - 1, 1);
377 
378     #undef RENDER_QUAD_VERTICAL
379 
380     /* horizontal filter 2 -> 3 */
381     glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, canvases[3]->framebuffers[0]);
382     glBindTexture (GL_TEXTURE_RECTANGLE_ARB, canvases[2]->texture.handles[0]);
383 
384     SCHRO_OPENGL_CHECK_ERROR
385 
386     #define RENDER_QUAD_HORIZONTAL(_x, _quad_width) \
387         schro_opengl_upsampled_frame_render_quad (shader, _x, 0,  _quad_width,\
388             height, width, height)
389 
390     RENDER_QUAD_HORIZONTAL (0, 1);
391 
392     if (width > 2) {
393       RENDER_QUAD_HORIZONTAL (1, 1);
394 
395       if (width > 4) {
396         RENDER_QUAD_HORIZONTAL (2, 1);
397 
398         if (width > 6) {
399           RENDER_QUAD_HORIZONTAL (3, 1);
400 
401            if (width > 8) {
402              RENDER_QUAD_HORIZONTAL (4, width - 8);
403            }
404 
405            RENDER_QUAD_HORIZONTAL (width - 4, 1);
406         }
407 
408         RENDER_QUAD_HORIZONTAL (width - 3, 1);
409       }
410 
411       RENDER_QUAD_HORIZONTAL (width - 2, 1);
412     }
413 
414     RENDER_QUAD_HORIZONTAL (width - 1, 1);
415 
416     #undef RENDER_QUAD_HORIZONTAL
417   }
418 
419   glUseProgramObjectARB (0);
420 #if SCHRO_OPENGL_UNBIND_TEXTURES
421   glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
422 #endif
423   glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
424 
425   schro_opengl_unlock (opengl);
426 }
427 
428 void
schro_frame_print(SchroFrame * frame,const char * name)429 schro_frame_print (SchroFrame *frame, const char* name)
430 {
431   printf ("schro_frame_print: %s\n", name);
432 
433   switch (SCHRO_FRAME_FORMAT_DEPTH (frame->format)) {
434     case SCHRO_FRAME_FORMAT_DEPTH_U8:
435       printf ("  depth:  U8\n");
436       break;
437     case SCHRO_FRAME_FORMAT_DEPTH_S16:
438       printf ("  depth:  S16\n");
439       break;
440     case SCHRO_FRAME_FORMAT_DEPTH_S32:
441       printf ("  depth:  S32\n");
442       break;
443     default:
444       printf ("  depth:  unknown\n");
445       break;
446   }
447 
448   printf ("  packed: %s\n", SCHRO_FRAME_IS_PACKED (frame->format) ? "yes": "no");
449   printf ("  width:  %i\n", frame->width);
450   printf ("  height: %i\n", frame->height);
451   printf ("  opengl: %s\n", SCHRO_FRAME_IS_OPENGL (frame) ? "yes": "no");
452 }
453 
454