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>
13 schro_opengl_canvas_push_convert (SchroOpenGLCanvas
*dest
, SchroFrameData
*src
,
14 void *texture_data
, int y_offset
, int height
)
18 int frame_stride
, texture_stride
, texture_channels
;
19 uint8_t *frame_data_u8
= NULL
;
20 int16_t *frame_data_s16
= NULL
;
21 uint8_t *texture_data_u8
= NULL
;
22 uint16_t *texture_data_u16
= NULL
;
23 int16_t *texture_data_s16
= NULL
;
24 float *texture_data_f32
= NULL
;
26 SCHRO_ASSERT (dest
!= NULL
);
27 SCHRO_ASSERT (src
!= NULL
);
28 SCHRO_ASSERT (dest
->format
== src
->format
);
29 SCHRO_ASSERT (dest
->width
== src
->width
);
30 SCHRO_ASSERT (dest
->height
== src
->height
);
31 SCHRO_ASSERT (texture_data
!= NULL
);
34 frame_stride
= src
->stride
;
35 texture_stride
= dest
->push
.stride
;
36 texture_channels
= SCHRO_FRAME_IS_PACKED (src
->format
)
37 ? 1 : dest
->texture
.channels
;
39 switch (SCHRO_FRAME_FORMAT_DEPTH (src
->format
)) {
40 case SCHRO_FRAME_FORMAT_DEPTH_U8
:
41 frame_data_u8
= SCHRO_FRAME_DATA_GET_LINE (src
, y_offset
);
43 if (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_U8_AS_F32
)) {
44 texture_data_f32
= (float *) texture_data
;
46 for (y
= 0; y
< height
; ++y
) {
47 for (x
= 0; x
< width
; ++x
) {
48 texture_data_f32
[x
* texture_channels
]
49 = (float) frame_data_u8
[x
] / 255.0;
52 texture_data_f32
= OFFSET (texture_data_f32
, texture_stride
);
53 frame_data_u8
= OFFSET (frame_data_u8
, frame_stride
);
56 texture_data_u8
= (uint8_t *) texture_data
;
58 if (texture_channels
> 1) {
59 for (y
= 0; y
< height
; ++y
) {
60 for (x
= 0; x
< width
; ++x
) {
61 texture_data_u8
[x
* texture_channels
] = frame_data_u8
[x
];
64 texture_data_u8
= OFFSET (texture_data_u8
, texture_stride
);
65 frame_data_u8
= OFFSET (frame_data_u8
, frame_stride
);
68 for (y
= 0; y
< height
; ++y
) {
69 orc_memcpy (texture_data_u8
, frame_data_u8
, width
);
71 texture_data_u8
= OFFSET (texture_data_u8
, texture_stride
);
72 frame_data_u8
= OFFSET (frame_data_u8
, frame_stride
);
78 case SCHRO_FRAME_FORMAT_DEPTH_S16
:
79 frame_data_s16
= SCHRO_FRAME_DATA_GET_LINE (src
, y_offset
);
81 if (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_S16_AS_U16
)) {
82 texture_data_u16
= (uint16_t *) texture_data
;
84 for (y
= 0; y
< height
; ++y
) {
85 for (x
= 0; x
< width
; ++x
) {
86 texture_data_u16
[x
* texture_channels
]
87 = (uint16_t) ((int32_t) frame_data_s16
[x
] + 32768);
90 texture_data_u16
= OFFSET (texture_data_u16
, texture_stride
);
91 frame_data_s16
= OFFSET (frame_data_s16
, frame_stride
);
93 } else if (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_S16_AS_F32
)) {
94 texture_data_f32
= (float *) texture_data
;
96 for (y
= 0; y
< height
; ++y
) {
97 for (x
= 0; x
< width
; ++x
) {
98 texture_data_f32
[x
* texture_channels
]
99 = (float) ((int32_t) frame_data_s16
[x
] + 32768) / 65535.0;
102 texture_data_f32
= OFFSET (texture_data_f32
, texture_stride
);
103 frame_data_s16
= OFFSET (frame_data_s16
, frame_stride
);
106 texture_data_s16
= (int16_t *) texture_data
;
108 if (texture_channels
> 1) {
109 for (y
= 0; y
< height
; ++y
) {
110 for (x
= 0; x
< width
; ++x
) {
111 texture_data_s16
[x
* texture_channels
] = frame_data_s16
[x
];
114 texture_data_s16
= OFFSET (texture_data_s16
, texture_stride
);
115 frame_data_s16
= OFFSET (frame_data_s16
, frame_stride
);
118 for (y
= 0; y
< height
; ++y
) {
119 orc_memcpy (texture_data_s16
, frame_data_s16
,
120 width
* sizeof (int16_t));
122 texture_data_s16
= OFFSET (texture_data_s16
, texture_stride
);
123 frame_data_s16
= OFFSET (frame_data_s16
, frame_stride
);
136 schro_opengl_frame_push (SchroFrame
*dest
, SchroFrame
*src
)
140 SchroOpenGLCanvas
*dest_canvas
= NULL
;
141 SchroOpenGL
*opengl
= NULL
;
143 SCHRO_ASSERT (dest
!= NULL
);
144 SCHRO_ASSERT (src
!= NULL
);
145 SCHRO_ASSERT (SCHRO_FRAME_IS_OPENGL (dest
));
146 SCHRO_ASSERT (!SCHRO_FRAME_IS_OPENGL (src
));
147 SCHRO_ASSERT (dest
->format
== src
->format
);
149 components
= SCHRO_FRAME_IS_PACKED (src
->format
) ? 1 : 3;
150 // FIXME: hack to store custom data per frame component
151 dest_canvas
= *((SchroOpenGLCanvas
**) dest
->components
[0].data
);
153 SCHRO_ASSERT (dest_canvas
!= NULL
);
155 opengl
= dest_canvas
->opengl
;
157 schro_opengl_lock (opengl
);
159 for (i
= 0; i
< components
; ++i
) {
160 // FIXME: hack to store custom data per frame component
161 dest_canvas
= *((SchroOpenGLCanvas
**) dest
->components
[i
].data
);
163 schro_opengl_canvas_push (dest_canvas
, src
->components
+ i
);
166 schro_opengl_unlock (opengl
);
170 schro_opengl_canvas_push (SchroOpenGLCanvas
*dest
, SchroFrameData
*src
)
173 int width
, height
, depth
;
174 int pixelbuffer_y_offset
, pixelbuffer_height
;
175 GLuint src_texture
= 0; // FIXME: don't create a new locale texture here
176 // but use a single global texture for such temporary
178 void *mapped_data
= NULL
;
179 void *tmp_data
= NULL
;
180 SchroOpenGLShader
*shader
;
182 SCHRO_ASSERT (dest
->format
== src
->format
);
183 SCHRO_ASSERT (dest
->width
== src
->width
);
184 SCHRO_ASSERT (dest
->height
== src
->height
);
185 SCHRO_ASSERT (dest
->texture
.handles
[0] != 0);
186 SCHRO_ASSERT (dest
->texture
.handles
[1] != 0);
187 SCHRO_ASSERT (dest
->framebuffers
[0] != 0);
188 SCHRO_ASSERT (dest
->framebuffers
[1] != 0);
191 height
= src
->height
;
192 depth
= SCHRO_FRAME_FORMAT_DEPTH (src
->format
);
194 schro_opengl_lock (dest
->opengl
);
196 if (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_RENDER_QUAD
)) {
197 glGenTextures (1, &src_texture
);
198 glBindTexture (GL_TEXTURE_RECTANGLE_ARB
, src_texture
);
199 glTexImage2D (GL_TEXTURE_RECTANGLE_ARB
, 0, dest
->texture
.internal_format
,
200 width
, height
, 0, dest
->texture
.pixel_format
, dest
->texture
.type
, NULL
);
201 glTexParameteri (GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MAG_FILTER
,
203 glTexParameteri (GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MIN_FILTER
,
205 glTexParameteri (GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
206 glTexParameteri (GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
207 glTexEnvi (GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
209 SCHRO_OPENGL_CHECK_ERROR
212 if ((SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_U8_PIXELBUFFER
) &&
213 depth
== SCHRO_FRAME_FORMAT_DEPTH_U8
) ||
214 (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_S16_PIXELBUFFER
) &&
215 depth
== SCHRO_FRAME_FORMAT_DEPTH_S16
)) {
216 pixelbuffer_y_offset
= 0;
218 for (i
= 0; i
< SCHRO_OPENGL_TRANSFER_PIXELBUFFERS
; ++i
) {
219 pixelbuffer_height
= dest
->push
.heights
[i
];
221 glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_EXT
, dest
->push
.pixelbuffers
[i
]);
222 glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB
,
223 dest
->push
.stride
* pixelbuffer_height
, NULL
, GL_STREAM_DRAW_ARB
);
225 mapped_data
= glMapBufferARB (GL_PIXEL_UNPACK_BUFFER_EXT
,
228 schro_opengl_canvas_push_convert (dest
, src
, mapped_data
,
229 pixelbuffer_y_offset
, pixelbuffer_height
);
231 glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_EXT
);
233 pixelbuffer_y_offset
+= pixelbuffer_height
;
235 SCHRO_OPENGL_CHECK_ERROR
238 if (!SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_RENDER_QUAD
)) {
239 glBindTexture (GL_TEXTURE_RECTANGLE_ARB
, dest
->texture
.handles
[0]);
242 pixelbuffer_y_offset
= 0;
244 if (dest
->push
.type
== GL_SHORT
) {
245 /* OpenGL maps signed values different to float values than unsigned
246 values. for S16 -32768 is mapped to -1.0 and 32767 to 1.0, for U16
247 0 is mapped to 0.0 and 65535 to 1.0. after this mapping scale and
248 bias are applied and the resulting value is clamped to [0..1].
249 with default scale = 1 and default bias = 0 all negative values
250 from S16 are clamped to 0.0, changing scale and bias to 0.5 gives
251 a unclamped mapping that doesn't discard all negative values for S16 */
252 glPixelTransferf (GL_RED_SCALE
, 0.5);
253 glPixelTransferf (GL_RED_BIAS
, 0.5);
256 for (i
= 0; i
< SCHRO_OPENGL_TRANSFER_PIXELBUFFERS
; ++i
) {
257 pixelbuffer_height
= dest
->push
.heights
[i
];
259 glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_EXT
, dest
->push
.pixelbuffers
[i
]);
261 SCHRO_OPENGL_CHECK_ERROR
263 if (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_DRAWPIXELS
)) {
264 glBindFramebufferEXT (GL_FRAMEBUFFER_EXT
, dest
->framebuffers
[0]);
266 glWindowPos2iARB (0, pixelbuffer_y_offset
);
267 glDrawPixels (width
, pixelbuffer_height
, dest
->texture
.pixel_format
,
268 dest
->push
.type
, NULL
);
270 glBindFramebufferEXT (GL_FRAMEBUFFER_EXT
, 0);
272 glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB
, 0, 0, pixelbuffer_y_offset
,
273 width
, pixelbuffer_height
, dest
->texture
.pixel_format
,
274 dest
->push
.type
, NULL
);
277 SCHRO_OPENGL_CHECK_ERROR
279 pixelbuffer_y_offset
+= pixelbuffer_height
;
282 if (dest
->push
.type
== GL_SHORT
) {
283 glPixelTransferf (GL_RED_SCALE
, 1);
284 glPixelTransferf (GL_RED_BIAS
, 0);
287 glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_EXT
, 0);
289 tmp_data
= schro_opengl_get_tmp (dest
->opengl
, dest
->push
.stride
* height
);
291 schro_opengl_canvas_push_convert (dest
, src
, tmp_data
, 0, height
);
293 if (!SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_RENDER_QUAD
)) {
294 glBindTexture (GL_TEXTURE_RECTANGLE_ARB
, dest
->texture
.handles
[0]);
297 if (dest
->push
.type
== GL_SHORT
) {
298 /* OpenGL maps signed values different to float values than unsigned
299 values. for S16 -32768 is mapped to -1.0 and 32767 to 1.0, for U16
300 0 is mapped to 0.0 and 65535 to 1.0. after this mapping scale and
301 bias are applied and the resulting value is clamped to [0..1].
302 with default scale = 1 and default bias = 0 all negative values
303 from S16 are clamped to 0.0, changing scale and bias to 0.5 gives
304 a unclamped mapping that doesn't discard all negative values for S16 */
305 glPixelTransferf (GL_RED_SCALE
, 0.5);
306 glPixelTransferf (GL_RED_BIAS
, 0.5);
309 if (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_DRAWPIXELS
)) {
310 glBindFramebufferEXT (GL_FRAMEBUFFER_EXT
, dest
->framebuffers
[0]);
312 glWindowPos2iARB (0, 0);
313 glDrawPixels (width
, height
, dest
->texture
.pixel_format
, dest
->push
.type
,
316 glBindFramebufferEXT (GL_FRAMEBUFFER_EXT
, 0);
318 glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB
, 0, 0, 0, width
, height
,
319 dest
->texture
.pixel_format
, dest
->push
.type
, tmp_data
);
322 if (dest
->push
.type
== GL_SHORT
) {
323 glPixelTransferf (GL_RED_SCALE
, 1);
324 glPixelTransferf (GL_RED_BIAS
, 0);
328 SCHRO_OPENGL_CHECK_ERROR
330 if (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_RENDER_QUAD
)) {
331 schro_opengl_setup_viewport (width
, height
);
333 glBindFramebufferEXT (GL_FRAMEBUFFER_EXT
, dest
->framebuffers
[0]);
335 SCHRO_OPENGL_CHECK_ERROR
337 if (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_SHADER
)) {
338 switch (SCHRO_FRAME_FORMAT_DEPTH (src
->format
)) {
339 case SCHRO_FRAME_FORMAT_DEPTH_U8
:
340 shader
= schro_opengl_shader_get (dest
->opengl
,
341 SCHRO_OPENGL_SHADER_COPY_U8
);
343 case SCHRO_FRAME_FORMAT_DEPTH_S16
:
344 shader
= schro_opengl_shader_get (dest
->opengl
,
345 SCHRO_OPENGL_SHADER_COPY_S16
);
352 glUseProgramObjectARB (shader
->program
);
353 glUniform1iARB (shader
->textures
[0], 0);
356 schro_opengl_render_quad (0, 0, width
, height
);
358 if (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_SHADER
)) {
359 glUseProgramObjectARB (0);
364 glBindFramebufferEXT (GL_FRAMEBUFFER_EXT
, 0);
366 SCHRO_OPENGL_CHECK_ERROR
369 #if SCHRO_OPENGL_UNBIND_TEXTURES
370 glBindTexture (GL_TEXTURE_RECTANGLE_ARB
, 0);
373 if (SCHRO_OPENGL_CANVAS_IS_FLAG_SET (PUSH_RENDER_QUAD
)) {
374 glDeleteTextures (1, &src_texture
);
377 schro_opengl_unlock (dest
->opengl
);