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