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
11 void
schro_opengl_wavelet_transform(SchroFrameData * frame_data,int filter)12 schro_opengl_wavelet_transform (SchroFrameData *frame_data, int filter)
13 {
14 SCHRO_ERROR ("unimplemented");
15 SCHRO_ASSERT (0);
16 }
17
18 void
schro_opengl_wavelet_vertical_deinterleave(SchroFrameData * frame_data)19 schro_opengl_wavelet_vertical_deinterleave (SchroFrameData *frame_data)
20 {
21 int width, height;
22 int framebuffer_index, texture_index;
23 SchroOpenGLCanvas *canvas = NULL;
24 SchroOpenGL *opengl = NULL;
25 SchroOpenGLShader *shader_copy = NULL;
26 SchroOpenGLShader *shader_vertical_deinterleave_l = NULL;
27 SchroOpenGLShader *shader_vertical_deinterleave_h = NULL;
28
29 SCHRO_ASSERT (SCHRO_FRAME_FORMAT_DEPTH (frame_data->format)
30 == SCHRO_FRAME_FORMAT_DEPTH_S16);
31 SCHRO_ASSERT (frame_data->width % 2 == 0);
32 SCHRO_ASSERT (frame_data->height % 2 == 0);
33
34 width = frame_data->width;
35 height = frame_data->height;
36 // FIXME: hack to store custom data per frame component
37 canvas = *((SchroOpenGLCanvas **) frame_data->data);
38
39 SCHRO_ASSERT (canvas != NULL);
40
41 opengl = canvas->opengl;
42
43 schro_opengl_lock (opengl);
44
45 shader_copy = schro_opengl_shader_get (opengl,
46 SCHRO_OPENGL_SHADER_COPY_S16);
47 shader_vertical_deinterleave_l = schro_opengl_shader_get (opengl,
48 SCHRO_OPENGL_SHADER_IIWT_S16_VERTICAL_DEINTERLEAVE_L);
49 shader_vertical_deinterleave_h = schro_opengl_shader_get (opengl,
50 SCHRO_OPENGL_SHADER_IIWT_S16_VERTICAL_DEINTERLEAVE_H);
51
52 SCHRO_ASSERT (shader_copy != NULL);
53 SCHRO_ASSERT (shader_vertical_deinterleave_l != NULL);
54 SCHRO_ASSERT (shader_vertical_deinterleave_h != NULL);
55
56 schro_opengl_setup_viewport (width, height);
57
58 SCHRO_OPENGL_CHECK_ERROR
59
60 #define SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES \
61 framebuffer_index = 1 - framebuffer_index; \
62 texture_index = 1 - texture_index; \
63 SCHRO_ASSERT (framebuffer_index != texture_index);
64
65 #define BIND_FRAMEBUFFER_AND_TEXTURE \
66 glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, \
67 canvas->framebuffers[framebuffer_index]); \
68 glBindTexture (GL_TEXTURE_RECTANGLE_ARB, \
69 canvas->texture.handles[texture_index]); \
70 SCHRO_OPENGL_CHECK_ERROR
71
72 framebuffer_index = 1;
73 texture_index = 0;
74
75 /* pass 1: vertical deinterleave */
76 BIND_FRAMEBUFFER_AND_TEXTURE
77
78 glUseProgramObjectARB (shader_vertical_deinterleave_l->program);
79 glUniform1iARB (shader_vertical_deinterleave_l->textures[0], 0);
80
81 schro_opengl_render_quad (0, 0, width, height / 2);
82
83 glUseProgramObjectARB (shader_vertical_deinterleave_h->program);
84 glUniform1iARB (shader_vertical_deinterleave_h->textures[0], 0);
85 glUniform2fARB (shader_vertical_deinterleave_h->offset, 0, height / 2);
86
87 schro_opengl_render_quad (0, height / 2, width, height / 2);
88
89 SCHRO_OPENGL_CHECK_ERROR
90
91 glFlush ();
92
93 /* pass 2: transfer data from secondary to primary framebuffer */
94 SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES
95 BIND_FRAMEBUFFER_AND_TEXTURE
96
97 glUseProgramObjectARB (shader_copy->program);
98 glUniform1iARB (shader_copy->textures[0], 0);
99
100 schro_opengl_render_quad (0, 0, width, height);
101
102 SCHRO_OPENGL_CHECK_ERROR
103
104 glFlush ();
105
106 #undef SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES
107 #undef BIND_FRAMEBUFFER_AND_TEXTURE
108
109 #if SCHRO_OPENGL_UNBIND_TEXTURES
110 glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
111 #endif
112 glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
113
114 schro_opengl_unlock (opengl);
115 }
116
117 static void
schro_opengl_wavelet_render_quad(SchroOpenGLShader * shader,int x,int y,int quad_width,int quad_height,int total_width,int total_height)118 schro_opengl_wavelet_render_quad (SchroOpenGLShader *shader, int x, int y,
119 int quad_width, int quad_height, int total_width, int total_height)
120 {
121 int x_inverse, y_inverse;
122 int two_x = 0, two_y = 0, one_x = 0, one_y = 0;
123
124 x_inverse = total_width - x - quad_width;
125 y_inverse = total_height - y - quad_height;
126
127 if (quad_width == total_width && quad_height < total_height) {
128 two_y = 2;
129 one_y = 1;
130 } else if (quad_width < total_width && quad_height == total_height) {
131 two_x = 2;
132 one_x = 1;
133 } else {
134 SCHRO_ERROR ("invalid quad to total relation");
135 SCHRO_ASSERT (0);
136 }
137
138 SCHRO_ASSERT (x_inverse >= 0);
139 SCHRO_ASSERT (y_inverse >= 0);
140
141 #define UNIFORM(_number, _operation, __x, __y) \
142 do { \
143 if (shader->_number##_##_operation != -1) { \
144 glUniform2fARB (shader->_number##_##_operation, \
145 __x < _number##_x ? __x : _number##_x, \
146 __y < _number##_y ? __y : _number##_y); \
147 } \
148 } while (0)
149
150 UNIFORM (two, decrease, x, y);
151 UNIFORM (one, decrease, x, y);
152 UNIFORM (one, increase, x_inverse, y_inverse);
153 UNIFORM (two, increase, x_inverse, y_inverse);
154
155 #undef UNIFORM
156
157 schro_opengl_render_quad (x, y, quad_width, quad_height);
158 }
159
160 void
schro_opengl_wavelet_inverse_transform(SchroFrameData * frame_data,int filter)161 schro_opengl_wavelet_inverse_transform (SchroFrameData *frame_data,
162 int filter)
163 {
164 int width, height, subband_width, subband_height;
165 int framebuffer_index, texture_index;
166 int filter_shift = FALSE;
167 SchroOpenGLCanvas *canvas = NULL;
168 SchroOpenGL *opengl = NULL;
169 SchroOpenGLShader *shader_copy = NULL;
170 SchroOpenGLShader *shader_filter_lp = NULL;
171 SchroOpenGLShader *shader_filter_hp = NULL;
172 SchroOpenGLShader *shader_vertical_interleave = NULL;
173 SchroOpenGLShader *shader_horizontal_interleave = NULL;
174 SchroOpenGLShader *shader_filter_shift = NULL;
175
176 SCHRO_ASSERT (SCHRO_FRAME_FORMAT_DEPTH (frame_data->format)
177 == SCHRO_FRAME_FORMAT_DEPTH_S16);
178 SCHRO_ASSERT (frame_data->width >= 2);
179 SCHRO_ASSERT (frame_data->height >= 2);
180 SCHRO_ASSERT (frame_data->width % 2 == 0);
181 SCHRO_ASSERT (frame_data->height % 2 == 0);
182
183 width = frame_data->width;
184 height = frame_data->height;
185 subband_width = width / 2;
186 subband_height = height / 2;
187 // FIXME: hack to store custom data per frame component
188 canvas = *((SchroOpenGLCanvas **) frame_data->data);
189
190 SCHRO_ASSERT (canvas != NULL);
191
192 opengl = canvas->opengl;
193
194 schro_opengl_lock (opengl);
195
196 shader_copy = schro_opengl_shader_get (opengl,
197 SCHRO_OPENGL_SHADER_COPY_S16);
198
199 SCHRO_ASSERT (shader_copy != NULL);
200
201 switch (filter) {
202 case SCHRO_WAVELET_DESLAURIES_DUBUC_9_7:
203 shader_filter_lp = schro_opengl_shader_get (opengl,
204 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_DESLAURIERS_DUBUC_9_7_Lp);
205 shader_filter_hp = schro_opengl_shader_get (opengl,
206 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_DESLAURIERS_DUBUC_9_7_Hp);
207
208 filter_shift = TRUE;
209 break;
210 case SCHRO_WAVELET_LE_GALL_5_3:
211 shader_filter_lp = schro_opengl_shader_get (opengl,
212 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_LE_GALL_5_3_Lp);
213 shader_filter_hp = schro_opengl_shader_get (opengl,
214 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_LE_GALL_5_3_Hp);
215
216 filter_shift = TRUE;
217 break;
218 case SCHRO_WAVELET_DESLAURIES_DUBUC_13_7:
219 shader_filter_lp = schro_opengl_shader_get (opengl,
220 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_DESLAURIERS_DUBUC_13_7_Lp);
221 shader_filter_hp = schro_opengl_shader_get (opengl,
222 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_DESLAURIERS_DUBUC_13_7_Hp);
223
224 filter_shift = TRUE;
225 break;
226 case SCHRO_WAVELET_HAAR_0:
227 shader_filter_lp = schro_opengl_shader_get (opengl,
228 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_HAAR_Lp);
229 shader_filter_hp = schro_opengl_shader_get (opengl,
230 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_HAAR_Hp);
231
232 filter_shift = FALSE;
233 break;
234 case SCHRO_WAVELET_HAAR_1:
235 shader_filter_lp = schro_opengl_shader_get (opengl,
236 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_HAAR_Lp);
237 shader_filter_hp = schro_opengl_shader_get (opengl,
238 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_HAAR_Hp);
239
240 filter_shift = TRUE;
241 break;
242 case SCHRO_WAVELET_FIDELITY:
243 SCHRO_ERROR ("fidelity filter is not implemented yet");
244 SCHRO_ASSERT (0);
245
246 filter_shift = FALSE;
247 break;
248 case SCHRO_WAVELET_DAUBECHIES_9_7:
249 SCHRO_ERROR ("daubechies 9,7 filter is not implemented yet");
250 SCHRO_ASSERT (0);
251
252 filter_shift = TRUE;
253 break;
254 default:
255 SCHRO_ERROR ("unknown filter %i", filter);
256 SCHRO_ASSERT (0);
257 break;
258 }
259
260 SCHRO_ASSERT (shader_filter_lp != NULL);
261 SCHRO_ASSERT (shader_filter_hp != NULL);
262
263 shader_vertical_interleave = schro_opengl_shader_get (opengl,
264 SCHRO_OPENGL_SHADER_IIWT_S16_VERTICAL_INTERLEAVE);
265 shader_horizontal_interleave = schro_opengl_shader_get (opengl,
266 SCHRO_OPENGL_SHADER_IIWT_S16_HORIZONTAL_INTERLEAVE);
267
268 SCHRO_ASSERT (shader_vertical_interleave != NULL);
269 SCHRO_ASSERT (shader_horizontal_interleave != NULL);
270
271 if (filter_shift) {
272 shader_filter_shift = schro_opengl_shader_get (opengl,
273 SCHRO_OPENGL_SHADER_IIWT_S16_FILTER_SHIFT);
274
275 SCHRO_ASSERT (shader_filter_shift);
276 } else {
277 shader_filter_shift = NULL;
278 }
279
280 schro_opengl_setup_viewport (width, height);
281
282 SCHRO_OPENGL_CHECK_ERROR
283
284 #define SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES \
285 framebuffer_index = 1 - framebuffer_index; \
286 texture_index = 1 - texture_index; \
287 SCHRO_ASSERT (framebuffer_index != texture_index);
288
289 #define BIND_FRAMEBUFFER_AND_TEXTURE \
290 glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, \
291 canvas->framebuffers[framebuffer_index]); \
292 glBindTexture (GL_TEXTURE_RECTANGLE_ARB, \
293 canvas->texture.handles[texture_index]); \
294 SCHRO_OPENGL_CHECK_ERROR
295
296 framebuffer_index = 1;
297 texture_index = 0;
298
299 /* pass 1: vertical filtering => XL + f(XH) = XL' */
300 BIND_FRAMEBUFFER_AND_TEXTURE
301
302 glUseProgramObjectARB (shader_filter_lp->program);
303 glUniform1iARB (shader_filter_lp->textures[0], 0);
304 glUniform2fARB (shader_filter_lp->offset, 0, subband_height);
305
306 #define RENDER_QUAD_VERTICAL_Lp(_y, _quad_height) \
307 schro_opengl_wavelet_render_quad (shader_filter_lp, 0, _y, width, \
308 _quad_height, width, height)
309
310 RENDER_QUAD_VERTICAL_Lp (0, 1);
311
312 if (subband_height > 2) {
313 RENDER_QUAD_VERTICAL_Lp (1, 1);
314
315 if (subband_height > 4) {
316 RENDER_QUAD_VERTICAL_Lp (2, subband_height - 4);
317 }
318
319 RENDER_QUAD_VERTICAL_Lp (subband_height - 2, 1);
320 }
321
322 RENDER_QUAD_VERTICAL_Lp (subband_height - 1, 1);
323
324 #undef RENDER_QUAD_VERTICAL_Lp
325
326 /* copy XH */
327 glUseProgramObjectARB (shader_copy->program);
328 glUniform1iARB (shader_copy->textures[0], 0);
329
330 schro_opengl_render_quad (0, subband_height, width, subband_height);
331
332 SCHRO_OPENGL_CHECK_ERROR
333
334 glFlush ();
335
336 /* pass 2: vertical filtering => f(XL') + XH = XH' */
337 SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES
338 BIND_FRAMEBUFFER_AND_TEXTURE
339
340 glUseProgramObjectARB (shader_filter_hp->program);
341 glUniform1iARB (shader_filter_hp->textures[0], 0);
342 glUniform2fARB (shader_filter_hp->offset, 0, subband_height);
343
344 #define RENDER_QUAD_VERTICAL_Hp(_y_offset, _quad_height) \
345 schro_opengl_wavelet_render_quad (shader_filter_hp, 0, \
346 subband_height + (_y_offset), width, _quad_height, width, height)
347
348 RENDER_QUAD_VERTICAL_Hp (0, 1);
349
350 if (subband_height > 2) {
351 RENDER_QUAD_VERTICAL_Hp (1, 1);
352
353 if (subband_height > 4) {
354 RENDER_QUAD_VERTICAL_Hp (2, subband_height - 4);
355 }
356
357 RENDER_QUAD_VERTICAL_Hp (subband_height - 2, 1);
358 }
359
360 RENDER_QUAD_VERTICAL_Hp (subband_height - 1, 1);
361
362 #undef RENDER_QUAD_VERTICAL_Hp
363
364 /* copy XL' */
365 glUseProgramObjectARB (shader_copy->program);
366 glUniform1iARB (shader_copy->textures[0], 0);
367
368 schro_opengl_render_quad (0, 0, width, subband_height);
369
370 SCHRO_OPENGL_CHECK_ERROR
371
372 glFlush ();
373
374 /* pass 3: vertical interleave => i(LL', LH') = L, i(HL', HH') = H */
375 SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES
376 BIND_FRAMEBUFFER_AND_TEXTURE
377
378 glUseProgramObjectARB (shader_vertical_interleave->program);
379 glUniform1iARB (shader_vertical_interleave->textures[0], 0);
380 glUniform2fARB (shader_vertical_interleave->offset, 0, subband_height);
381
382 schro_opengl_render_quad (0, 0, width, height);
383
384 SCHRO_OPENGL_CHECK_ERROR
385
386 glFlush ();
387
388 /* pass 4: horizontal filtering => L + f(H) = L' */
389 SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES
390 BIND_FRAMEBUFFER_AND_TEXTURE
391
392 glUseProgramObjectARB (shader_filter_lp->program);
393 glUniform1iARB (shader_filter_lp->textures[0], 0);
394 glUniform2fARB (shader_filter_lp->offset, subband_width, 0);
395
396 #define RENDER_QUAD_HORIZONTAL_Lp(_x, _quad_width) \
397 schro_opengl_wavelet_render_quad (shader_filter_lp, _x, 0, _quad_width, \
398 height, width, height)
399
400 RENDER_QUAD_HORIZONTAL_Lp (0, 1);
401
402 if (subband_width > 2) {
403 RENDER_QUAD_HORIZONTAL_Lp (1, 1);
404
405 if (subband_width > 4) {
406 RENDER_QUAD_HORIZONTAL_Lp (2, subband_width - 4);
407 }
408
409 RENDER_QUAD_HORIZONTAL_Lp (subband_width - 2, 1);
410 }
411
412 RENDER_QUAD_HORIZONTAL_Lp (subband_width - 1, 1);
413
414 #undef RENDER_QUAD_HORIZONTAL_Lp
415
416 /* copy H */
417 glUseProgramObjectARB (shader_copy->program);
418 glUniform1iARB (shader_copy->textures[0], 0);
419
420 schro_opengl_render_quad (subband_width, 0, subband_width, height);
421
422 SCHRO_OPENGL_CHECK_ERROR
423
424 glFlush ();
425
426 /* pass 5: horizontal filtering => f(L') + H = H' */
427 SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES
428 BIND_FRAMEBUFFER_AND_TEXTURE
429
430 glUseProgramObjectARB (shader_filter_hp->program);
431 glUniform1iARB (shader_filter_hp->textures[0], 0);
432 glUniform2fARB (shader_filter_hp->offset, subband_width, 0);
433
434 #define RENDER_QUAD_HORIZONTAL_Hp(_x_offset, _quad_width) \
435 schro_opengl_wavelet_render_quad (shader_filter_hp, \
436 subband_width + (_x_offset), 0, _quad_width, height, width, height);
437
438 RENDER_QUAD_HORIZONTAL_Hp (0, 1);
439
440 if (subband_width > 2) {
441 RENDER_QUAD_HORIZONTAL_Hp (1, 1);
442
443 if (subband_width > 4) {
444 RENDER_QUAD_HORIZONTAL_Hp (2, subband_width - 4);
445 }
446
447 RENDER_QUAD_HORIZONTAL_Hp (subband_width - 2, 1);
448 }
449
450 RENDER_QUAD_HORIZONTAL_Hp (subband_width - 1, 1);
451
452 #undef RENDER_QUAD_HORIZONTAL_Hp
453
454 /* copy L' */
455 glUseProgramObjectARB (shader_copy->program);
456 glUniform1iARB (shader_copy->textures[0], 0);
457
458 schro_opengl_render_quad (0, 0, subband_width, height);
459
460 SCHRO_OPENGL_CHECK_ERROR
461
462 glFlush ();
463
464 /* pass 6: horizontal interleave => i(L', H') = LL */
465 SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES
466 BIND_FRAMEBUFFER_AND_TEXTURE
467
468 glUseProgramObjectARB (shader_horizontal_interleave->program);
469 glUniform1iARB (shader_horizontal_interleave->textures[0], 0);
470 glUniform2fARB (shader_horizontal_interleave->offset, width / 2, 0);
471
472 schro_opengl_render_quad (0, 0, width, height);
473
474 SCHRO_OPENGL_CHECK_ERROR
475
476 glFlush ();
477
478 /* pass 7: filter shift */
479 if (filter_shift) {
480 SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES
481 BIND_FRAMEBUFFER_AND_TEXTURE
482
483 glUseProgramObjectARB (shader_filter_shift->program);
484 glUniform1iARB (shader_filter_shift->textures[0], 0);
485
486 schro_opengl_render_quad (0, 0, width, height);
487
488 SCHRO_OPENGL_CHECK_ERROR
489
490 glFlush ();
491 }
492
493 /* pass 8: transfer data from secondary to primary framebuffer if previous
494 pass result wasn't rendered into the primary framebuffer */
495 if (framebuffer_index != 0) {
496 SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES
497 BIND_FRAMEBUFFER_AND_TEXTURE
498
499 glUseProgramObjectARB (shader_copy->program);
500 glUniform1iARB (shader_copy->textures[0], 0);
501
502 schro_opengl_render_quad (0, 0, width, height);
503
504 SCHRO_OPENGL_CHECK_ERROR
505
506 glFlush ();
507 }
508
509 #undef SWITCH_FRAMEBUFFER_AND_TEXTURE_INDICES
510 #undef BIND_FRAMEBUFFER_AND_TEXTURE
511
512 glUseProgramObjectARB (0);
513 #if SCHRO_OPENGL_UNBIND_TEXTURES
514 glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
515 #endif
516 glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
517
518 schro_opengl_unlock (opengl);
519 }
520
521