Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2020
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Compositor sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 :
27 : #include "texturing.h"
28 : #include "visual_manager.h"
29 : #include "nodes_stacks.h"
30 : #include "gl_inc.h"
31 :
32 :
33 :
34 : /*tx flags*/
35 : enum
36 : {
37 : /*signal video data must be sent to 2D raster*/
38 : TX_NEEDS_RASTER_LOAD = (1<<1),
39 : /*signal video data must be sent to 3D hw*/
40 : TX_NEEDS_HW_LOAD = (1<<2),
41 :
42 : /*OpenGL texturing flags*/
43 :
44 : /*texture is rect*/
45 : TX_IS_RECT = (1<<10),
46 : /*texture emulates power of two through larger buffer and upscaling*/
47 : TX_EMULE_POW2 = (1<<11),
48 : /*texture is flipped*/
49 : TX_IS_FLIPPED = (1<<12),
50 : /*texture must be converted*/
51 : TX_CONV_8BITS = (1<<13),
52 :
53 : TX_FIRST_UPLOAD_FREEZE = (1<<14),
54 : TX_FIRST_UPLOAD_FREEZE_DONE = (1<<15),
55 : };
56 :
57 :
58 : struct __texture_wrapper
59 : {
60 : u32 flags;
61 :
62 : /*2D texturing*/
63 : GF_EVGStencil * tx_raster;
64 : u8 *conv_data;
65 : GF_Matrix texcoordmatrix;
66 :
67 : //format of converted texture for 10->8 bit or non RGB->RGB if no shader support
68 : u32 conv_format;
69 : //size info of converted data
70 : u32 conv_w, conv_h, conv_stride;
71 :
72 : /*3D OpenGL texturing*/
73 : #ifndef GPAC_DISABLE_3D
74 : /*opengl texture id*/
75 : u32 blend_mode;
76 : //scaling factor when emulating pow2
77 : Fixed conv_wscale, conv_hscale;
78 :
79 : //texture wrapper object
80 : GF_GLTextureWrapper tx;
81 :
82 : /* gl_format: GL_RGB, GL_RGBA, GL_LUMINANCE or GL_LUMINANCE_ALPHA*/
83 : u32 gl_format;
84 : /* gl_type: 2D texture or rectangle*/
85 : u32 gl_type;
86 :
87 : /*FBO framebuffer ID*/
88 : u32 fbo_id;
89 : /*FBO texture attachment ID*/
90 : u32 fbo_txid;
91 : /*FBO depth buffer attacghment ID*/
92 : u32 depth_id;
93 : #endif
94 :
95 : #ifdef GF_SR_USE_DEPTH
96 : char *depth_data;
97 : #endif
98 : };
99 :
100 1261 : GF_Err gf_sc_texture_allocate(GF_TextureHandler *txh)
101 : {
102 1261 : if (txh->tx_io) return GF_OK;
103 1261 : GF_SAFEALLOC(txh->tx_io, struct __texture_wrapper);
104 1261 : if (!txh->tx_io) return GF_OUT_OF_MEM;
105 1261 : return GF_OK;
106 : }
107 :
108 388 : GF_Err gf_sc_texture_configure_conversion(GF_TextureHandler *txh)
109 : {
110 388 : txh->flags &= ~TX_CONV_8BITS;
111 388 : if (txh->compositor->out8b) {
112 : u32 osize;
113 0 : if (txh->pixelformat == GF_PIXEL_YUV_10) {
114 0 : txh->tx_io->conv_format = GF_PIXEL_YUV;
115 : }
116 0 : else if (txh->pixelformat == GF_PIXEL_NV12_10) {
117 0 : txh->tx_io->conv_format = GF_PIXEL_NV12;
118 : }
119 0 : else if (txh->pixelformat == GF_PIXEL_NV21_10) {
120 0 : txh->tx_io->conv_format = GF_PIXEL_NV21;
121 : }
122 0 : else if (txh->pixelformat == GF_PIXEL_YUV422_10) {
123 0 : txh->tx_io->conv_format = GF_PIXEL_YUV422;
124 : }
125 0 : else if (txh->pixelformat == GF_PIXEL_YUV444_10) {
126 0 : txh->tx_io->conv_format = GF_PIXEL_YUV444;
127 : } else {
128 0 : return GF_OK;
129 : }
130 0 : osize = 0;
131 0 : txh->tx_io->conv_stride = 0;
132 0 : gf_pixel_get_size_info(txh->tx_io->conv_format, txh->width, txh->height, &osize, &txh->tx_io->conv_stride, NULL, NULL, NULL);
133 0 : txh->tx_io->conv_data = (char*)gf_realloc(txh->tx_io->conv_data, osize);
134 0 : txh->flags |= TX_CONV_8BITS;
135 : }
136 : return GF_OK;
137 : }
138 :
139 :
140 :
141 1384 : static void release_txio(struct __texture_wrapper *tx_io)
142 : {
143 :
144 : #ifndef GPAC_DISABLE_3D
145 1384 : if (tx_io->fbo_id) {
146 9 : compositor_3d_delete_fbo(&tx_io->fbo_id, &tx_io->fbo_txid, &tx_io->depth_id, GF_FALSE);
147 : } else {
148 1375 : gf_gl_txw_reset(&tx_io->tx);
149 : }
150 : #endif
151 :
152 1384 : if (tx_io->conv_data) gf_free(tx_io->conv_data);
153 :
154 : #ifdef GF_SR_USE_DEPTH
155 1384 : if (tx_io->depth_data) gf_free(tx_io->depth_data);
156 : #endif
157 :
158 1384 : gf_free(tx_io);
159 1384 : }
160 :
161 1999 : void gf_sc_texture_release(GF_TextureHandler *txh)
162 : {
163 1999 : if (txh->vout_udta && txh->compositor->video_out->ReleaseTexture) {
164 0 : txh->compositor->video_out->ReleaseTexture(txh->compositor->video_out, txh);
165 0 : txh->vout_udta = NULL;
166 : }
167 :
168 1999 : if (txh->tx_io) {
169 1384 : gf_sc_lock(txh->compositor, 1);
170 :
171 1384 : if (txh->tx_io->tx_raster) {
172 1115 : gf_evg_stencil_delete(txh->tx_io->tx_raster);
173 1115 : txh->tx_io->tx_raster = NULL;
174 : }
175 :
176 1384 : if (gf_th_id()==txh->compositor->video_th_id) {
177 1384 : release_txio(txh->tx_io);
178 : } else {
179 0 : gf_list_add(txh->compositor->textures_gc, txh->tx_io);
180 : }
181 1384 : txh->tx_io = NULL;
182 :
183 1384 : gf_sc_lock(txh->compositor, 0);
184 : }
185 1999 : }
186 :
187 44059 : void gf_sc_texture_cleanup_hw(GF_Compositor *compositor)
188 : {
189 88118 : while (gf_list_count(compositor->textures_gc)) {
190 0 : struct __texture_wrapper *tx_io = (struct __texture_wrapper *) gf_list_last(compositor->textures_gc);
191 0 : gf_list_rem_last(compositor->textures_gc);
192 :
193 0 : release_txio(tx_io);
194 : }
195 44059 : }
196 :
197 :
198 :
199 7540 : GF_Err gf_sc_texture_set_data(GF_TextureHandler *txh)
200 : {
201 : #ifndef GPAC_DISABLE_3D
202 : u8 *data=NULL;
203 7540 : GF_FilterFrameInterface *fifce = txh->frame_ifce;
204 : #endif
205 7540 : txh->tx_io->flags |= TX_NEEDS_RASTER_LOAD | TX_NEEDS_HW_LOAD;
206 :
207 : #ifndef GPAC_DISABLE_3D
208 7540 : data = txh->data;
209 : //10->8 bit conversion
210 7540 : if (txh->flags & TX_CONV_8BITS) {
211 : GF_VideoSurface dst, src;
212 : GF_Err e;
213 : memset(&dst, 0, sizeof(GF_VideoSurface));
214 : memset(&src, 0, sizeof(GF_VideoSurface));
215 0 : dst.width = txh->width;
216 0 : dst.height = txh->height;
217 0 : dst.pitch_y = txh->tx_io->conv_stride;
218 0 : dst.video_buffer = txh->tx_io->conv_data;
219 0 : dst.pixel_format = txh->tx_io->conv_format;
220 :
221 0 : src.width = txh->width;
222 0 : src.height = txh->height;
223 0 : src.pitch_y = txh->stride;
224 0 : src.video_buffer = txh->data;
225 0 : src.pixel_format = txh->pixelformat;
226 :
227 0 : if (txh->frame_ifce) {
228 : u32 st_y, st_u, st_v;
229 0 : txh->frame_ifce->get_plane(txh->frame_ifce, 0, (const u8 **) &src.video_buffer, &st_y);
230 0 : txh->frame_ifce->get_plane(txh->frame_ifce, 1, (const u8 **) &src.u_ptr, &st_u);
231 0 : txh->frame_ifce->get_plane(txh->frame_ifce, 2, (const u8 **) &src.v_ptr, &st_v);
232 0 : if (src.video_buffer) src.pitch_y = st_y;
233 : }
234 :
235 0 : e = gf_stretch_bits(&dst, &src, NULL, NULL, 0xFF, GF_FALSE, NULL, NULL);
236 0 : if (e) {
237 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D] Failed to convert 10-bits to 8-bit texture: %s\n", gf_error_to_string(e) ));
238 0 : return e;
239 : }
240 : fifce = NULL;
241 0 : data = dst.video_buffer;
242 : }
243 : #endif
244 :
245 :
246 : #if !defined(GPAC_DISABLE_3D) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_GLES2)
247 : //PBO mode: start pushing the texture
248 7540 : if (data && !fifce && (txh->tx_io->tx.pbo_state!=GF_GL_PBO_NONE)) {
249 0 : txh->tx_io->tx.pbo_state = GF_GL_PBO_PUSH;
250 0 : gf_gl_txw_upload(&txh->tx_io->tx, data, fifce);
251 :
252 : //we just pushed our texture to the GPU, release
253 0 : if (txh->frame_ifce) {
254 0 : gf_sc_texture_release_stream(txh);
255 : }
256 : }
257 : #endif
258 : return GF_OK;
259 : }
260 :
261 2422 : void gf_sc_texture_reset(GF_TextureHandler *txh)
262 : {
263 : #ifndef GPAC_DISABLE_3D
264 2422 : if (txh->tx_io->tx.nb_textures) {
265 11 : GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Texturing] Releasing OpenGL texture\n"));
266 11 : gf_gl_txw_reset(&txh->tx_io->tx);
267 : }
268 2422 : if (txh->tx_io->fbo_id) {
269 0 : compositor_3d_delete_fbo(&txh->tx_io->fbo_id, &txh->tx_io->fbo_txid, &txh->tx_io->depth_id, GF_FALSE);
270 : }
271 2422 : txh->tx_io->flags |= TX_NEEDS_HW_LOAD;
272 : #endif
273 :
274 : #ifdef GF_SR_USE_DEPTH
275 2422 : if (txh->tx_io->depth_data) {
276 0 : gf_free(txh->tx_io->depth_data);
277 0 : txh->tx_io->depth_data = NULL;
278 : }
279 : #endif
280 :
281 2422 : if (txh->vout_udta && txh->compositor->video_out->ReleaseTexture) {
282 0 : txh->compositor->video_out->ReleaseTexture(txh->compositor->video_out, txh);
283 0 : txh->vout_udta = NULL;
284 : }
285 2422 : }
286 :
287 : #ifndef GPAC_DISABLE_3D
288 :
289 11076 : void gf_sc_texture_set_blend_mode(GF_TextureHandler *txh, u32 mode)
290 : {
291 11076 : if (txh->tx_io) txh->tx_io->blend_mode = mode;
292 11076 : }
293 :
294 17156 : void tx_bind_with_mode(GF_TextureHandler *txh, Bool transparent, u32 blend_mode, Bool no_bind, u32 glsl_prog_id)
295 : {
296 17156 : if (!txh->tx_io->gl_type)
297 : return;
298 : #ifndef GPAC_USE_GLES2
299 17156 : if (!no_bind)
300 17156 : glEnable(txh->tx_io->gl_type);
301 :
302 17156 : switch (blend_mode) {
303 3026 : case TX_BLEND:
304 3026 : if (txh->transparent) glEnable(GL_BLEND);
305 3026 : GLTEXENV(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
306 3026 : break;
307 8216 : case TX_REPLACE:
308 8216 : if (txh->transparent) glEnable(GL_BLEND);
309 8216 : GLTEXENV(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
310 8216 : break;
311 4033 : case TX_MODULATE:
312 4033 : if (txh->transparent) glEnable(GL_BLEND);
313 : #ifdef GPAC_USE_GLES1X
314 : GLTEXENV(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
315 : #else
316 4033 : GLTEXENV(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
317 : #endif
318 4033 : break;
319 1881 : case TX_DECAL:
320 : default:
321 1881 : if (((txh->tx_io->gl_format==GL_LUMINANCE)) || (txh->tx_io->gl_format==GL_LUMINANCE_ALPHA)) {
322 0 : GLTEXENV(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND/*GL_MODULATE*/);
323 : } else {
324 1881 : GLTEXENV(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
325 : }
326 : break;
327 : }
328 : #else
329 : if (txh->transparent) glEnable(GL_BLEND);
330 : //blend_mode for ES2.0 can be implemented inside the fragment shader if desired
331 : #endif
332 :
333 17156 : if (!no_bind) {
334 17156 : gf_gl_txw_bind(&txh->tx_io->tx, "maintx", glsl_prog_id, 0);
335 : }
336 : }
337 :
338 3674 : void tx_bind(GF_TextureHandler *txh)
339 : {
340 3674 : if (txh->tx_io )
341 3674 : tx_bind_with_mode(txh, txh->transparent, txh->tx_io->blend_mode, 0, 0);
342 3674 : }
343 :
344 13524 : void gf_sc_texture_disable(GF_TextureHandler *txh)
345 : {
346 13524 : if (!txh || !txh->tx_io)
347 : return;
348 :
349 : #ifndef GPAC_USE_GLES1X
350 13484 : glBindTexture(txh->tx_io->gl_type, 0);
351 : #endif
352 :
353 : #if !defined(GPAC_USE_GLES2)
354 13484 : glDisable(txh->tx_io->gl_type);
355 : #endif
356 :
357 13484 : if (txh->transparent)
358 6162 : glDisable(GL_BLEND);
359 :
360 13484 : gf_sc_texture_check_pause_on_first_load(txh, GF_FALSE);
361 13484 : txh->compositor->visual->bound_tx_pix_fmt = 0;
362 : }
363 :
364 :
365 0 : Bool tx_can_use_rect_ext(GF_Compositor *compositor, GF_TextureHandler *txh)
366 : {
367 : #ifndef GPAC_DISABLE_VRML
368 : u32 i, j, count;
369 : #endif
370 :
371 : // compositor->gl_caps.yuv_texture = 0;
372 0 : if (!compositor->gl_caps.rect_texture) return 0;
373 0 : if (compositor->rext) return 1;
374 : /*this happens ONLY with text texturing*/
375 0 : if (!txh->owner) return 0;
376 :
377 : #ifndef GPAC_DISABLE_VRML
378 0 : count = gf_node_get_parent_count(txh->owner);
379 :
380 : /*background 2D can use RECT ext without pb*/
381 0 : if (gf_node_get_tag(txh->owner)==TAG_MPEG4_Background2D) return 1;
382 : /*if a bitmap is using the texture force using RECT*/
383 0 : for (i=0; i<count; i++) {
384 0 : GF_Node *n = gf_node_get_parent(txh->owner, i);
385 0 : if (gf_node_get_tag(n)==TAG_MPEG4_Appearance) {
386 0 : count = gf_node_get_parent_count(n);
387 0 : for (j=0; j<count; j++) {
388 0 : M_Shape *s = (M_Shape *) gf_node_get_parent(n, j);
389 0 : if (s->geometry && (gf_node_get_tag((GF_Node *)s)==TAG_MPEG4_Shape) && (gf_node_get_tag(s->geometry)==TAG_MPEG4_Bitmap)) return 1;
390 : }
391 : }
392 : }
393 : #endif /*GPAC_DISABLE_VRML*/
394 : return 0;
395 : }
396 :
397 :
398 380 : static Bool tx_setup_format(GF_TextureHandler *txh)
399 : {
400 : u32 npow_w, npow_h;
401 : Bool is_pow2, use_rect, flip;
402 380 : GF_Compositor *compositor = (GF_Compositor *)txh->compositor;
403 :
404 : /*first setup, this will force recompute bounds in case used with bitmap - we could refine and only
405 : invalidate for bitmaps only*/
406 380 : if (txh->owner)
407 109 : gf_node_dirty_set(txh->owner, 0, 1);
408 :
409 380 : npow_w = gf_get_next_pow2(txh->width);
410 380 : npow_h = gf_get_next_pow2(txh->height);
411 :
412 380 : flip = (txh->tx_io->flags & TX_IS_FLIPPED);
413 380 : is_pow2 = ((npow_w==txh->width) && (npow_h==txh->height)) ? 1 : 0;
414 380 : txh->tx_io->flags = 0;
415 380 : txh->tx_io->gl_type = GL_TEXTURE_2D;
416 :
417 : /* all textures can be used in GLES2 */
418 : #ifdef GPAC_USE_GLES2
419 : use_rect = GF_TRUE;
420 : #else
421 :
422 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
423 380 : if (!compositor->shader_mode_disabled || compositor->gl_caps.npot || compositor->gl_caps.has_shaders) {
424 : use_rect = GF_TRUE;
425 : } else
426 : #endif
427 : {
428 0 : use_rect = tx_can_use_rect_ext(compositor, txh);
429 :
430 0 : if (!is_pow2 && use_rect) {
431 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
432 0 : txh->tx_io->gl_type = GL_TEXTURE_RECTANGLE_EXT;
433 : #endif
434 0 : txh->tx_io->flags = TX_IS_RECT;
435 : }
436 : }
437 : #endif
438 :
439 380 : txh->tx_io->gl_format = 0;
440 380 : switch (txh->pixelformat) {
441 6 : case GF_PIXEL_GREYSCALE:
442 6 : txh->tx_io->gl_format = GL_LUMINANCE;
443 6 : break;
444 0 : case GF_PIXEL_ALPHAGREY:
445 : case GF_PIXEL_GREYALPHA:
446 0 : txh->tx_io->gl_format = GL_LUMINANCE_ALPHA;
447 0 : break;
448 45 : case GF_PIXEL_RGB:
449 45 : txh->tx_io->gl_format = GL_RGB;
450 45 : break;
451 0 : case GF_PIXEL_BGR:
452 0 : txh->tx_io->gl_format = GL_RGB;
453 0 : break;
454 0 : case GF_PIXEL_BGRX:
455 0 : txh->tx_io->gl_format = GL_RGBA;
456 0 : break;
457 318 : case GF_PIXEL_RGBX:
458 : case GF_PIXEL_RGBA:
459 318 : txh->tx_io->gl_format = GL_RGBA;
460 318 : break;
461 : #ifndef GPAC_USE_GLES1X
462 0 : case GF_PIXEL_ARGB:
463 0 : if (!compositor->gl_caps.bgra_texture) return 0;
464 0 : txh->tx_io->gl_format = GL_BGRA_EXT;
465 0 : break;
466 : #endif
467 11 : case GF_PIXEL_YUV:
468 : case GF_PIXEL_YVU:
469 : case GF_PIXEL_YUV_10:
470 : case GF_PIXEL_YUV422:
471 : case GF_PIXEL_YUV422_10:
472 : case GF_PIXEL_YUV444:
473 : case GF_PIXEL_YUV444_10:
474 : case GF_PIXEL_NV21:
475 : case GF_PIXEL_NV21_10:
476 : case GF_PIXEL_NV12:
477 : case GF_PIXEL_NV12_10:
478 : case GF_PIXEL_YUYV:
479 : case GF_PIXEL_YVYU:
480 : case GF_PIXEL_VYUY:
481 : case GF_PIXEL_UYVY:
482 : case GF_PIXEL_GL_EXTERNAL:
483 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
484 11 : if (!compositor->visual->compositor->shader_mode_disabled) {
485 : break;
486 : }
487 : #endif
488 0 : if (!use_rect && compositor->epow2) txh->tx_io->flags = TX_EMULE_POW2;
489 0 : txh->tx_io->gl_format = GL_RGB;
490 0 : break;
491 :
492 : //fallthrough
493 0 : case GF_PIXEL_YUVA:
494 : case GF_PIXEL_YUVA444:
495 : case GF_PIXEL_YUVD:
496 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
497 0 : if (!compositor->visual->compositor->shader_mode_disabled) {
498 : break;
499 : }
500 : #endif
501 0 : if (!use_rect && compositor->epow2) txh->tx_io->flags = TX_EMULE_POW2;
502 0 : txh->tx_io->gl_format = GL_RGBA;
503 0 : break;
504 :
505 0 : case GF_PIXEL_RGBD:
506 : case GF_PIXEL_RGB_DEPTH:
507 0 : if (!use_rect && compositor->epow2) txh->tx_io->flags = TX_EMULE_POW2;
508 0 : txh->tx_io->gl_format = GL_RGB;
509 0 : break;
510 0 : default:
511 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Unknown pixel format %s\n", gf_4cc_to_str(txh->pixelformat) ));
512 : return 0;
513 : }
514 :
515 11 : if (flip) txh->tx_io->flags |= TX_IS_FLIPPED;
516 :
517 : /*in case the ID has been lost, resetup*/
518 380 : if (!txh->tx_io->tx.nb_textures) {
519 380 : u32 pfmt = txh->pixelformat;
520 380 : u32 stride = txh->stride;
521 : Bool full_range = GF_FALSE;
522 : s32 cmx = GF_CICP_MX_UNSPECIFIED;
523 380 : if (txh->stream && txh->stream->odm && txh->stream->odm->pid) {
524 : const GF_PropertyValue *p;
525 72 : p = gf_filter_pid_get_property(txh->stream->odm->pid, GF_PROP_PID_COLR_RANGE);
526 72 : if (p && p->value.boolean) full_range = GF_TRUE;
527 72 : p = gf_filter_pid_get_property(txh->stream->odm->pid, GF_PROP_PID_COLR_MX);
528 72 : if (p) cmx = p->value.uint;
529 : }
530 :
531 380 : txh->tx_io->tx.pbo_state = (txh->compositor->gl_caps.pbo && txh->compositor->pbo) ? GF_GL_PBO_BOTH : GF_GL_PBO_NONE;
532 380 : if (txh->tx_io->conv_format) {
533 2 : stride = txh->tx_io->conv_stride;
534 : pfmt = txh->tx_io->conv_format;
535 : }
536 380 : gf_gl_txw_setup(&txh->tx_io->tx, pfmt, txh->width, txh->height, stride, 0, GF_TRUE, NULL, full_range, cmx);
537 : }
538 : return 1;
539 : }
540 :
541 0 : char *gf_sc_texture_get_data(GF_TextureHandler *txh, u32 *pix_format)
542 : {
543 3670 : if (txh->tx_io->conv_data) {
544 0 : *pix_format = txh->tx_io->conv_format;
545 0 : return txh->tx_io->conv_data;
546 : }
547 0 : *pix_format = txh->pixelformat;
548 3670 : return txh->data;
549 : }
550 :
551 : /*note about conversion: we consider that a texture without a stream attached is generated by the compositor
552 : hence is never flipped. Otherwise all textures attached to stream are flipped in order to match uv coords*/
553 3669 : Bool gf_sc_texture_convert(GF_TextureHandler *txh)
554 : {
555 : GF_VideoSurface src, dst;
556 : u32 out_stride, i, j, bpp;
557 3669 : GF_Compositor *compositor = (GF_Compositor *)txh->compositor;
558 :
559 3669 : if (!txh->needs_refresh) return 1;
560 :
561 : #if !defined(GPAC_DISABLE_3D) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
562 3058 : if (!txh->compositor->shader_mode_disabled) {
563 3057 : txh->tx_io->flags |= TX_NEEDS_HW_LOAD;
564 3057 : return 1;
565 : }
566 : #endif
567 :
568 1 : switch (txh->pixelformat) {
569 0 : case GF_PIXEL_ARGB:
570 0 : if (!compositor->gl_caps.bgra_texture) return 0;
571 : goto common;
572 :
573 0 : case GF_PIXEL_RGBD:
574 0 : if (txh->compositor->depth_gl_type==GF_SC_DEPTH_GL_NONE) {
575 : bpp = 4;
576 : break;
577 : }
578 : case GF_PIXEL_BGR:
579 : bpp = 3;
580 0 : break;
581 : case GF_PIXEL_BGRX:
582 : bpp = 4;
583 : break;
584 : case GF_PIXEL_GREYSCALE:
585 : case GF_PIXEL_ALPHAGREY:
586 : case GF_PIXEL_GREYALPHA:
587 : case GF_PIXEL_RGB:
588 : case GF_PIXEL_RGBX:
589 : case GF_PIXEL_RGBA:
590 1 : common:
591 1 : txh->tx_io->conv_format = txh->pixelformat;
592 1 : txh->tx_io->flags |= TX_NEEDS_HW_LOAD;
593 :
594 1 : if (!(txh->tx_io->flags & TX_IS_RECT)) return 1;
595 0 : if (txh->flags & GF_SR_TEXTURE_NO_GL_FLIP) return 1;
596 : //FIXME - we really want to go for shaders on RGB as well to avoid this copy on rect ext ...
597 :
598 0 : if (!txh->tx_io->conv_data) {
599 0 : txh->tx_io->conv_data = gf_malloc(sizeof(char)*txh->stride*txh->height);
600 0 : txh->tx_io->conv_format = txh->pixelformat;
601 : }
602 : assert(txh->tx_io->conv_data );
603 : assert(txh->data );
604 : /*if texture is using RECT extension, flip image manually because
605 : texture transforms are not supported in this case ...*/
606 0 : for (i=0; i<txh->height; i++) {
607 0 : memcpy(txh->tx_io->conv_data + (txh->height - 1 - i) * txh->stride, txh->data + i*txh->stride, txh->stride);
608 : }
609 :
610 0 : txh->tx_io->flags |= TX_IS_FLIPPED;
611 0 : return 1;
612 0 : case GF_PIXEL_YUV:
613 : case GF_PIXEL_YVU:
614 : case GF_PIXEL_YUV_10:
615 : case GF_PIXEL_YUV422:
616 : case GF_PIXEL_YUV422_10:
617 : case GF_PIXEL_YUV444:
618 : case GF_PIXEL_YUV444_10:
619 : case GF_PIXEL_NV12:
620 : case GF_PIXEL_NV12_10:
621 : case GF_PIXEL_NV21:
622 : case GF_PIXEL_NV21_10:
623 : case GF_PIXEL_YUYV:
624 : case GF_PIXEL_YVYU:
625 : case GF_PIXEL_UYVY:
626 : case GF_PIXEL_VYUY:
627 : bpp = 3;
628 0 : break;
629 : case GF_PIXEL_YUVD:
630 : case GF_PIXEL_YUVA:
631 : case GF_PIXEL_YUVA444:
632 : bpp = 4;
633 : break;
634 0 : default:
635 0 : txh->tx_io->conv_format = 0;
636 0 : return 0;
637 : }
638 0 : if (!txh->tx_io->conv_data) {
639 0 : if (txh->tx_io->flags & TX_EMULE_POW2) {
640 : /*convert video to a po of 2 WITHOUT SCALING VIDEO*/
641 0 : txh->tx_io->conv_w = gf_get_next_pow2(txh->width);
642 0 : txh->tx_io->conv_h = gf_get_next_pow2(txh->height);
643 0 : txh->tx_io->conv_data = (char*)gf_malloc(sizeof(char) * bpp * txh->tx_io->conv_w * txh->tx_io->conv_h);
644 0 : memset(txh->tx_io->conv_data , 0, sizeof(char) * bpp * txh->tx_io->conv_w * txh->tx_io->conv_h);
645 0 : txh->tx_io->conv_wscale = INT2FIX(txh->width) / txh->tx_io->conv_w;
646 0 : txh->tx_io->conv_hscale = INT2FIX(txh->height) / txh->tx_io->conv_h;
647 : } else {
648 0 : txh->tx_io->conv_data = (char*)gf_malloc(sizeof(char) * bpp * txh->width * txh->height);
649 0 : memset(txh->tx_io->conv_data, 0, sizeof(char) * bpp * txh->width * txh->height);
650 : }
651 : }
652 0 : out_stride = bpp * ((txh->tx_io->flags & TX_EMULE_POW2) ? txh->tx_io->conv_w : txh->width);
653 0 : txh->tx_io->conv_stride = out_stride;
654 :
655 :
656 : memset(&src, 0, sizeof(GF_VideoSurface));
657 : memset(&dst, 0, sizeof(GF_VideoSurface));
658 0 : dst.width = src.width = txh->width;
659 0 : dst.height = src.height = txh->height;
660 : dst.is_hardware_memory = src.is_hardware_memory = 0;
661 :
662 : src.pitch_x = 0;
663 0 : src.pitch_y = txh->stride;
664 0 : src.pixel_format = txh->pixelformat;
665 0 : src.video_buffer = txh->data;
666 :
667 : dst.pitch_x = 0;
668 0 : dst.pitch_y = out_stride;
669 :
670 0 : dst.video_buffer = txh->tx_io->conv_data;
671 0 : switch (txh->pixelformat) {
672 0 : case GF_PIXEL_YUYV:
673 : case GF_PIXEL_YUV:
674 : case GF_PIXEL_YVU:
675 : case GF_PIXEL_YUV_10:
676 : case GF_PIXEL_YUV422:
677 : case GF_PIXEL_YUV422_10:
678 : case GF_PIXEL_YUV444:
679 : case GF_PIXEL_YUV444_10:
680 : case GF_PIXEL_NV21:
681 : case GF_PIXEL_NV12:
682 : case GF_PIXEL_NV12_10:
683 : case GF_PIXEL_BGR:
684 : case GF_PIXEL_BGRX:
685 0 : txh->tx_io->conv_format = dst.pixel_format = GF_PIXEL_RGB;
686 : /*stretch and flip*/
687 0 : gf_stretch_bits(&dst, &src, NULL, NULL, 0xFF, !txh->is_flipped, NULL, NULL);
688 0 : if ( !txh->is_flipped)
689 0 : txh->flags |= GF_SR_TEXTURE_NO_GL_FLIP;
690 : break;
691 0 : case GF_PIXEL_YUVD:
692 0 : if (txh->compositor->depth_gl_type==GF_SC_DEPTH_GL_NONE) {
693 0 : src.pixel_format = GF_PIXEL_YUV;
694 0 : txh->tx_io->conv_format = GF_PIXEL_RGB_DEPTH;
695 0 : dst.pixel_format = GF_PIXEL_RGB;
696 0 : dst.pitch_y = 3*txh->width;
697 : /*stretch YUV->RGB*/
698 0 : gf_stretch_bits(&dst, &src, NULL, NULL, 0xFF, 1, NULL, NULL);
699 : /*copy over Depth plane*/
700 0 : memcpy(dst.video_buffer + 3*txh->width*txh->height, txh->data + 3*txh->stride*txh->height/2, txh->width*txh->height);
701 : } else {
702 0 : txh->tx_io->conv_format = GF_PIXEL_RGBD;
703 0 : dst.pixel_format = GF_PIXEL_RGBD;
704 : /*stretch*/
705 0 : gf_stretch_bits(&dst, &src, NULL, NULL, 0xFF, 0, NULL, NULL);
706 : }
707 0 : txh->flags |= GF_SR_TEXTURE_NO_GL_FLIP;
708 0 : break;
709 0 : case GF_PIXEL_RGBD:
710 0 : if (txh->compositor->depth_gl_type==GF_SC_DEPTH_GL_NONE) {
711 0 : dst.pitch_y = 3*txh->width;
712 0 : txh->tx_io->conv_format = GF_PIXEL_RGB_DEPTH;
713 0 : dst.pixel_format = GF_PIXEL_RGB;
714 :
715 0 : for (j=0; j<txh->height; j++) {
716 0 : u8 *src_p = (u8 *) txh->data + (txh->height-j-1)*txh->stride;
717 0 : u8 *dst_p = (u8 *) txh->tx_io->conv_data + j*3*txh->width;
718 0 : u8 *dst_d = (u8 *) txh->tx_io->conv_data + txh->height*3*txh->width + j*txh->width;
719 :
720 0 : for (i=0; i<txh->width; i++) {
721 0 : *dst_p++ = src_p[i*4];
722 0 : *dst_p++ = src_p[i*4 + 1];
723 0 : *dst_p++ = src_p[i*4 + 2];
724 0 : *dst_d++ = src_p[i*4 + 3];
725 : }
726 : }
727 0 : txh->flags |= GF_SR_TEXTURE_NO_GL_FLIP;
728 : }
729 : break;
730 : }
731 0 : txh->tx_io->flags |= TX_NEEDS_HW_LOAD;
732 0 : return 1;
733 : }
734 :
735 : #endif
736 :
737 18374 : Bool gf_sc_texture_push_image(GF_TextureHandler *txh, Bool generate_mipmaps, Bool for2d)
738 : {
739 : #ifndef GPAC_DISABLE_3D
740 : char *data;
741 : u32 pixel_format;
742 18374 : int nb_views = 1, nb_layers = 1;
743 : u32 push_time;
744 :
745 18374 : if (txh->stream) {
746 10483 : gf_mo_get_nb_views(txh->stream, &nb_views);
747 10483 : gf_mo_get_nb_layers(txh->stream, &nb_layers);
748 : }
749 : // if (txh->frame_ifce || nb_views == 1) nb_frames = 1;
750 : // else if (nb_layers) nb_frames = nb_layers;
751 :
752 : #endif
753 :
754 18374 : if (for2d) {
755 : Bool load_tx = 0;
756 4950 : if (!txh->data) return 0;
757 4950 : if (!txh->tx_io) {
758 124 : GF_SAFEALLOC(txh->tx_io, struct __texture_wrapper);
759 124 : if (!txh->tx_io) return 0;
760 : }
761 4950 : if (!txh->tx_io->tx_raster) {
762 296 : txh->tx_io->tx_raster = gf_evg_stencil_new(GF_STENCIL_TEXTURE);
763 296 : if (!txh->tx_io->tx_raster) return 0;
764 : load_tx = 1;
765 : }
766 4950 : if (txh->tx_io->flags & TX_NEEDS_RASTER_LOAD) {
767 : load_tx = 1;
768 431 : txh->tx_io->flags &= ~TX_NEEDS_RASTER_LOAD;
769 : }
770 4519 : if (load_tx) {
771 555 : const u8 *pData = txh->data;
772 555 : const u8 *pU=NULL, *pV=NULL, *pA=NULL;
773 555 : u32 stride = txh->stride;
774 555 : u32 stride_uv=0;
775 555 : u32 stride_alpha=0;
776 : GF_Err e=GF_OK;
777 555 : if (txh->frame_ifce) {
778 0 : pData=NULL;
779 0 : if (txh->frame_ifce->get_plane) {
780 0 : e = txh->frame_ifce->get_plane(txh->frame_ifce, 0, &pData, &stride);
781 0 : if (!e && txh->nb_planes>1)
782 0 : e = txh->frame_ifce->get_plane(txh->frame_ifce, 1, &pU, &stride_uv);
783 0 : if (!e && txh->nb_planes>2)
784 0 : e = txh->frame_ifce->get_plane(txh->frame_ifce, 2, &pV, &stride_uv);
785 0 : if (!e && txh->nb_planes>3)
786 0 : e = txh->frame_ifce->get_plane(txh->frame_ifce, 3, &pA, &stride_alpha);
787 : }
788 : }
789 555 : if (!pData) {
790 0 : if (!txh->compositor->last_error)
791 0 : txh->compositor->last_error = GF_NOT_SUPPORTED;
792 0 : return 0;
793 : }
794 :
795 555 : if (!e)
796 555 : e = gf_evg_stencil_set_texture_planes(txh->tx_io->tx_raster, txh->width, txh->height, (GF_PixelFormat) txh->pixelformat, pData, txh->stride, pU, pV, stride_uv, pA, stride_alpha);
797 :
798 555 : if (e != GF_OK) {
799 0 : if (!txh->compositor->last_error)
800 0 : txh->compositor->last_error = e;
801 : return 0;
802 : }
803 555 : txh->compositor->last_error = GF_OK;
804 : }
805 : return 1;
806 : }
807 :
808 : #ifndef GPAC_DISABLE_3D
809 :
810 13424 : if (! (txh->tx_io->flags & TX_NEEDS_HW_LOAD) ) return 1;
811 :
812 3977 : if (txh->tx_io->fbo_id) {
813 : return 1;
814 : }
815 : GL_CHECK_ERR()
816 :
817 3670 : if (txh->data) {
818 : //reconfig from GL textures to non-GL output
819 3669 : if (!txh->frame_ifce && !txh->tx_io->tx.internal_textures) {
820 377 : gf_gl_txw_reset(&txh->tx_io->tx);
821 : }
822 : //reconfig from non-GL output to GL textures
823 3292 : else if (txh->tx_io->tx.internal_textures
824 3292 : && txh->frame_ifce
825 0 : && txh->frame_ifce->get_gl_texture
826 : ) {
827 0 : gf_gl_txw_reset(&txh->tx_io->tx);
828 : }
829 : }
830 3670 : if (txh->data) {
831 : /*convert image*/
832 3669 : gf_sc_texture_convert(txh);
833 : }
834 :
835 3670 : txh->tx_io->tx.frame_ifce = txh->frame_ifce;
836 :
837 : /*in case the ID has been lost, resetup*/
838 3670 : if (!txh->tx_io->tx.nb_textures) {
839 : /*force setup of image*/
840 378 : txh->needs_refresh = 1;
841 378 : tx_setup_format(txh);
842 378 : GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Texturing] Allocating OpenGL texture\n"));
843 : }
844 3670 : if (!txh->tx_io->gl_type)
845 : return 0;
846 :
847 : GL_CHECK_ERR()
848 3670 : tx_bind(txh);
849 : GL_CHECK_ERR()
850 :
851 3670 : txh->tx_io->flags &= ~TX_NEEDS_HW_LOAD;
852 : data = gf_sc_texture_get_data(txh, &pixel_format);
853 3670 : if (!data) return 0;
854 :
855 3669 : push_time = gf_sys_clock();
856 :
857 3669 : gf_sc_texture_check_pause_on_first_load(txh, GF_TRUE);
858 :
859 : #ifdef GPAC_USE_TINYGL
860 : glTexImage2D(txh->tx_io->gl_type, 0, txh->tx_io->gl_format, w, h, 0, txh->tx_io->gl_format, GL_UNSIGNED_BYTE, (unsigned char *) data);
861 :
862 : #else
863 :
864 3669 : if (txh->frame_ifce && txh->frame_ifce->get_gl_texture ) {
865 0 : if (txh->tx_io->tx.internal_textures) {
866 0 : glDeleteTextures(txh->tx_io->tx.nb_textures, txh->tx_io->tx.textures);
867 0 : txh->tx_io->tx.internal_textures = GF_FALSE;
868 : }
869 : }
870 3669 : if (txh->tx_io->tx.pbo_state == GF_GL_PBO_PUSH)
871 0 : txh->tx_io->tx.pbo_state = GF_GL_PBO_TEXIMG;
872 :
873 : GL_CHECK_ERR()
874 3669 : gf_gl_txw_upload(&txh->tx_io->tx, data, txh->frame_ifce);
875 : GL_CHECK_ERR()
876 :
877 : #endif
878 :
879 3669 : push_time = gf_sys_clock() - push_time;
880 :
881 3669 : txh->nb_frames ++;
882 3669 : txh->upload_time += push_time;
883 :
884 : #ifndef GPAC_DISABLE_LOG
885 3669 : if (txh->stream) {
886 : u32 ck;
887 1037 : gf_mo_get_object_time(txh->stream, &ck);
888 1037 : GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[GL Texture] Texture (CTS %u) %d ms after due date - Pushed %s in %d ms - average push time %d ms (PBO enabled %s)\n", txh->last_frame_time, ck - txh->last_frame_time, txh->tx_io->tx.is_yuv ? "YUV textures" : "texture", push_time, txh->upload_time / txh->nb_frames, txh->tx_io->tx.pbo_state ? "yes" : "no"));
889 : }
890 : #endif
891 : return 1;
892 :
893 : #endif
894 : return 0;
895 : }
896 :
897 :
898 : #ifndef GPAC_DISABLE_3D
899 :
900 152 : u32 gf_sc_texture_get_gl_id(GF_TextureHandler *txh)
901 : {
902 152 : return (txh->tx_io && txh->tx_io->tx.nb_textures) ? txh->tx_io->tx.textures[0] : 0;
903 : }
904 :
905 : #ifndef GPAC_USE_TINYGL
906 2 : void gf_sc_copy_to_texture(GF_TextureHandler *txh)
907 : {
908 : /*in case the ID has been lost, resetup*/
909 2 : if (!txh->tx_io->tx.nb_textures) {
910 2 : tx_setup_format(txh);
911 : }
912 :
913 : GL_CHECK_ERR()
914 :
915 2 : tx_bind(txh);
916 :
917 : GL_CHECK_ERR()
918 :
919 : #ifdef GPAC_USE_GLES2
920 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
921 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
922 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
923 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
924 : glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
925 : #endif
926 : GL_CHECK_ERR()
927 :
928 2 : if (txh->compositor->fbo_id) compositor_3d_enable_fbo(txh->compositor, GF_TRUE);
929 2 : glCopyTexImage2D(txh->tx_io->gl_type, 0, txh->tx_io->gl_format, 0, 0, txh->width, txh->height, 0);
930 2 : if (txh->compositor->fbo_id) compositor_3d_enable_fbo(txh->compositor, GF_FALSE);
931 :
932 : #ifndef GPAC_USE_GLES2
933 2 : glDisable(txh->tx_io->gl_type);
934 : #endif
935 : GL_CHECK_ERR()
936 2 : }
937 :
938 9 : GF_Err gf_sc_texture_setup_fbo(GF_TextureHandler *txh)
939 : {
940 9 : txh->tx_io->gl_type = GL_TEXTURE_2D;
941 9 : return compositor_3d_setup_fbo(txh->width, txh->height, &txh->tx_io->fbo_id, &txh->tx_io->fbo_txid, &txh->tx_io->depth_id);
942 : }
943 :
944 604 : void gf_sc_texture_enable_fbo(GF_TextureHandler *txh, Bool enable)
945 : {
946 : #ifndef GPAC_USE_GLES1X
947 604 : if (txh->tx_io && txh->tx_io->fbo_id)
948 604 : glBindFramebuffer(GL_FRAMEBUFFER, enable ? txh->tx_io->fbo_id : 0);
949 : GL_CHECK_ERR()
950 604 : if (!enable)
951 302 : glBindTexture(GL_TEXTURE_2D, 0);
952 : #endif
953 604 : }
954 :
955 :
956 : #endif
957 :
958 : #ifndef GPAC_USE_TINYGL
959 :
960 0 : void gf_sc_copy_to_stencil(GF_TextureHandler *txh)
961 : {
962 : u32 i, hy;
963 : char *tmp=NULL;
964 :
965 : /*in case the ID has been lost, resetup*/
966 0 : if (!txh->data || !txh->tx_io->tx_raster)
967 : return;
968 :
969 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[GL Texture] Copying GL backbuffer %dx%d@PF=%s to systems memory\n", txh->width, txh->height, gf_4cc_to_str(txh->pixelformat) ));
970 :
971 0 : if (txh->compositor->fbo_id) compositor_3d_enable_fbo(txh->compositor, GF_TRUE);
972 :
973 0 : if (txh->pixelformat==GF_PIXEL_RGBA) {
974 0 : glReadPixels(0, 0, txh->width, txh->height, GL_RGBA, GL_UNSIGNED_BYTE, txh->data);
975 0 : } else if (txh->pixelformat==GF_PIXEL_RGB) {
976 0 : glReadPixels(0, 0, txh->width, txh->height, GL_RGB, GL_UNSIGNED_BYTE, txh->data);
977 : }
978 : #ifdef GF_SR_USE_DEPTH
979 0 : else if (txh->pixelformat==GF_PIXEL_RGBDS) {
980 : /*we'll work with one alpha bit (=shape). we'll take the heaviest weighted as this threshold*/
981 0 : glReadPixels(0, 0, txh->width, txh->height, GL_RGBA, GL_UNSIGNED_BYTE, txh->data);
982 :
983 : /*NOTES on OpenGL's z-buffer perspective inversion:
984 : * option 1: extract float depth buffer, undoing depth perspective transform PIXEL per PIXEL and then
985 : * convert to byte (computationally costly)
986 : *
987 : * option 2: use gain and offset to make up an approximation of the linear z-buffer (the original)
988 : * it can be achieved by scaling the interval where the inflection point is located
989 : * i.e. z' = G*z - (G - 1), the offset so that z still belongs to [0..1]*
990 : */
991 :
992 : //glPixelTransferf(GL_DEPTH_SCALE, txh->compositor->OGLDepthGain);
993 : //glPixelTransferf(GL_DEPTH_BIAS, txh->compositor->OGLDepthOffset);
994 :
995 : #ifndef GPAC_USE_GLES1X
996 : /*obtain depthmap*/
997 0 : if (!txh->tx_io->depth_data) txh->tx_io->depth_data = (char*)gf_malloc(sizeof(char)*txh->width*txh->height);
998 0 : glReadPixels(0, 0, txh->width, txh->height, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, txh->tx_io->depth_data);
999 : /* depth = alpha & 0xfe
1000 : shape = plan alpha & 0x01 */
1001 :
1002 : /*this corresponds to the RGBDS ordering*/
1003 0 : for (i=0; i<txh->height*txh->width; i++) {
1004 : u8 alpha;
1005 : //inversion
1006 0 : u8 ds = (char) (255 - (int)txh->tx_io->depth_data[i]);
1007 : /*get alpha*/
1008 0 : alpha = (txh->data[i*4 + 3]);
1009 :
1010 : /* if heaviest-weighted alpha bit is set (>128) , turn on shape bit*/
1011 : //if (ds & 0x80) depth |= 0x01;
1012 0 : if (alpha & 0x80) ds = (ds >> 1) | 0x80;
1013 : else ds = 0x0;
1014 0 : txh->data[i*4+3] = ds; /*insert depth onto alpha*/
1015 : }
1016 : #endif
1017 :
1018 : }
1019 : #endif /*GF_SR_USE_DEPTH*/
1020 :
1021 0 : if (txh->compositor->fbo_id) compositor_3d_enable_fbo(txh->compositor, GF_FALSE);
1022 :
1023 : /*flip image because of openGL*/
1024 0 : tmp = (char*)gf_malloc(sizeof(char)*txh->stride);
1025 0 : hy = txh->height/2;
1026 0 : for (i=0; i<hy; i++) {
1027 0 : memcpy(tmp, txh->data + i*txh->stride, txh->stride);
1028 0 : memcpy(txh->data + i*txh->stride, txh->data + (txh->height - 1 - i) * txh->stride, txh->stride);
1029 0 : memcpy(txh->data + (txh->height - 1 - i) * txh->stride, tmp, txh->stride);
1030 : }
1031 0 : gf_free(tmp);
1032 : //dump depth and rgbds texture
1033 :
1034 : }
1035 : #else
1036 :
1037 : void gf_get_tinygl_depth(GF_TextureHandler *txh)
1038 : {
1039 : glReadPixels(0, 0, txh->width, txh->height, GL_RGBDS, GL_UNSIGNED_BYTE, txh->data);
1040 : }
1041 : #endif
1042 :
1043 : #endif
1044 :
1045 13552 : Bool gf_sc_texture_get_transform(GF_TextureHandler *txh, GF_Node *tx_transform, GF_Matrix *mx, Bool for_picking)
1046 : {
1047 : #ifndef GPAC_DISABLE_3D
1048 13552 : int nb_views=1;
1049 : #endif
1050 : Bool ret = 0;
1051 27104 : gf_mx_init(*mx);
1052 :
1053 : #ifndef GPAC_DISABLE_3D
1054 13552 : gf_mo_get_nb_views(txh->stream, &nb_views);
1055 :
1056 : #ifdef GPAC_CONFIG_ANDROID
1057 : if (txh->stream && txh->tx_io->gl_type == GL_TEXTURE_EXTERNAL_OES) {
1058 : gf_mx_copy(*mx, txh->tx_io->texcoordmatrix);
1059 : ret = 1;
1060 : }
1061 : #endif // GPAC_CONFIG_ANDROID
1062 13552 : if (nb_views>1 && !txh->frame_ifce) {
1063 0 : if (txh->compositor->visual->current_view%2 != 0 && !txh->compositor->multiview_mode){
1064 0 : gf_mx_add_translation(mx, 0, 0.5f, 0);
1065 : }
1066 0 : gf_mx_add_scale(mx, FIX_ONE, 0.5f, FIX_ONE);
1067 : ret = 1;
1068 : }
1069 :
1070 13552 : if (txh->stream && (txh->compositor->fpack==GF_3D_STEREO_TOP)) {
1071 0 : if ((txh->compositor->visual->current_view % 2 != 0) && !txh->compositor->multiview_mode) {
1072 0 : gf_mx_add_translation(mx, 0, 0.5f, 0);
1073 : }
1074 0 : gf_mx_add_scale(mx, FIX_ONE, 0.5f, FIX_ONE);
1075 : ret = 1;
1076 : }
1077 : #endif
1078 :
1079 : /*flip image if requested*/
1080 13552 : if (! (txh->flags & GF_SR_TEXTURE_NO_GL_FLIP) && !(txh->tx_io->flags & TX_IS_FLIPPED) && !for_picking) {
1081 : /*flip it*/
1082 8226 : gf_mx_add_scale(mx, FIX_ONE, -FIX_ONE, FIX_ONE);
1083 : /*and translate it to handle repeatS/repeatT*/
1084 8226 : gf_mx_add_translation(mx, 0, -FIX_ONE, 0);
1085 : ret = 1;
1086 : }
1087 :
1088 : /*WATCHOUT: GL_TEXTURE_RECTANGLE coords are w, h not 1.0, 1.0 (but not with shaders, we do the txcoord conversion in the fragment shader*/
1089 13552 : if (txh->tx_io->flags & TX_IS_RECT) {
1090 : #ifndef GPAC_DISABLE_3D
1091 0 : if (!for_picking && !txh->tx_io->tx.is_yuv) {
1092 0 : gf_mx_add_scale(mx, INT2FIX(txh->width), INT2FIX(txh->height), FIX_ONE);
1093 : ret = 1;
1094 : }
1095 : #endif
1096 : }
1097 13552 : else if (txh->tx_io->flags & TX_EMULE_POW2) {
1098 : #ifndef GPAC_DISABLE_3D
1099 0 : gf_mx_add_scale(mx, txh->tx_io->conv_wscale, txh->tx_io->conv_hscale, FIX_ONE);
1100 : /*disable any texture transforms when emulating pow2 textures*/
1101 : tx_transform = NULL;
1102 : ret = 1;
1103 : #endif
1104 : }
1105 :
1106 : #ifndef GPAC_DISABLE_X3D
1107 13552 : if (tx_transform) {
1108 : GF_Matrix tmp;
1109 495 : switch (gf_node_get_tag(tx_transform)) {
1110 348 : case TAG_MPEG4_TextureTransform:
1111 : case TAG_X3D_TextureTransform:
1112 : {
1113 : GF_Matrix2D mat;
1114 : M_TextureTransform *tt = (M_TextureTransform *)tx_transform;
1115 348 : gf_mx2d_init(mat);
1116 :
1117 : /*cf VRML spec: Tc' = -C \D7 S \D7 R \D7 C \D7 T \D7 Tc*/
1118 348 : gf_mx2d_add_translation(&mat, -tt->center.x, -tt->center.y);
1119 348 : gf_mx2d_add_scale(&mat, tt->scale.x, tt->scale.y);
1120 348 : if (fabs(tt->rotation) > FIX_EPSILON) gf_mx2d_add_rotation(&mat, tt->center.x, tt->center.y, tt->rotation);
1121 348 : gf_mx2d_add_translation(&mat, tt->center.x, tt->center.y);
1122 :
1123 348 : gf_mx2d_add_translation(&mat, tt->translation.x, tt->translation.y);
1124 :
1125 348 : if (ret) {
1126 298 : gf_mx_from_mx2d(&tmp, &mat);
1127 298 : gf_mx_add_matrix(mx, &tmp);
1128 : } else {
1129 50 : gf_mx_from_mx2d(mx, &mat);
1130 : }
1131 : ret = 1;
1132 : }
1133 348 : break;
1134 147 : case TAG_MPEG4_TransformMatrix2D:
1135 : {
1136 : M_TransformMatrix2D *tm = (M_TransformMatrix2D *)tx_transform;
1137 : memset(tmp.m, 0, sizeof(Fixed)*16);
1138 147 : tmp.m[0] = tm->mxx;
1139 147 : tmp.m[4] = tm->mxy; /*0*/ tmp.m[12] = tm->tx;
1140 147 : tmp.m[1] = tm->myx;
1141 147 : tmp.m[5] = tm->myy; /*0*/ tmp.m[13] = tm->ty;
1142 : /*rest is all 0 excep both diag*/
1143 147 : tmp.m[10] = tmp.m[15] = FIX_ONE;
1144 :
1145 147 : if (ret) {
1146 147 : gf_mx_add_matrix(mx, &tmp);
1147 : } else {
1148 : gf_mx_copy(*mx, tmp);
1149 : }
1150 : ret = 1;
1151 : }
1152 : break;
1153 : default:
1154 : break;
1155 : }
1156 : }
1157 : #endif /*GPAC_DISABLE_X3D*/
1158 :
1159 13552 : return ret;
1160 : }
1161 :
1162 6935 : Bool gf_sc_texture_is_transparent(GF_TextureHandler *txh)
1163 : {
1164 : #ifdef GPAC_DISABLE_VRML
1165 : return txh->transparent;
1166 : #else
1167 : M_MatteTexture *matte;
1168 6935 : if (!txh->matteTexture) return txh->transparent;
1169 : matte = (M_MatteTexture *)txh->matteTexture;
1170 0 : if (!matte->operation.buffer) return txh->transparent;
1171 0 : if (matte->alphaSurface) return 1;
1172 0 : if (!strcmp(matte->operation.buffer, "COLOR_MATRIX")) return 1;
1173 0 : return txh->transparent;
1174 : #endif
1175 : }
1176 :
1177 : #ifndef GPAC_DISABLE_3D
1178 :
1179 14334 : u32 gf_sc_texture_enable_ex(GF_TextureHandler *txh, GF_Node *tx_transform, GF_Rect *bounds)
1180 : {
1181 : GF_Matrix mx;
1182 : Bool res;
1183 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
1184 : GF_GLProgInstance *prog;
1185 : #endif
1186 : GF_VisualManager *root_visual;
1187 :
1188 14334 : if (!txh || !txh->tx_io) return 0;
1189 13484 : root_visual = (GF_VisualManager *) txh->compositor->visual;
1190 :
1191 13484 : if (txh->stream && !txh->stream->pck) {
1192 69 : if (txh->tx_io->tx.nb_textures) {
1193 69 : txh->tx_io->tx.frame_ifce = NULL;
1194 69 : goto skip_push;
1195 : }
1196 : return 0;
1197 : }
1198 13415 : if (root_visual->has_material_2d) { // mat2d (hence no lights)
1199 4094 : root_visual->active_glsl_flags &= ~GF_GL_HAS_LIGHT;
1200 : }
1201 :
1202 : #ifndef GPAC_DISABLE_VRML
1203 13415 : if (txh->matteTexture) {
1204 : //not supported yet
1205 : return 0;
1206 : }
1207 : #endif
1208 :
1209 14004 : if (txh->compute_gradient_matrix && gf_sc_texture_needs_reload(txh) ) {
1210 316 : compositor_gradient_update(txh);
1211 : }
1212 13415 : if (!txh->pixelformat)
1213 : return 0;
1214 :
1215 13415 : if (!txh->stream || txh->data || txh->frame_ifce) {
1216 13415 : gf_rmt_begin_gl(gf_sc_texture_push_image);
1217 13415 : glGetError();
1218 13415 : res = gf_sc_texture_push_image(txh, 0, 0);
1219 13415 : gf_rmt_end_gl();
1220 13415 : glGetError();
1221 13415 : if (!res) return 0;
1222 : }
1223 :
1224 13415 : skip_push:
1225 :
1226 13484 : gf_rmt_begin_gl(gf_sc_texture_enable);
1227 13484 : glGetError();
1228 :
1229 13484 : if (bounds && txh->compute_gradient_matrix) {
1230 : GF_Matrix2D mx2d;
1231 0 : txh->compute_gradient_matrix(txh, bounds, &mx2d, 1);
1232 0 : gf_mx_from_mx2d(&mx, &mx2d);
1233 0 : visual_3d_set_texture_matrix(root_visual, &mx);
1234 : }
1235 13484 : else if (gf_sc_texture_get_transform(txh, tx_transform, &mx, 0)) {
1236 8226 : visual_3d_set_texture_matrix(root_visual, &mx);
1237 : } else {
1238 5258 : visual_3d_set_texture_matrix(root_visual, NULL);
1239 : }
1240 :
1241 13484 : txh->flags |= GF_SR_TEXTURE_USED;
1242 13484 : root_visual->active_glsl_flags |= GF_GL_HAS_TEXTURE;
1243 13484 : root_visual->bound_tx_pix_fmt = txh->pixelformat;
1244 :
1245 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
1246 13484 : prog = visual_3d_check_program_exists(root_visual, root_visual->active_glsl_flags, txh->pixelformat);
1247 :
1248 13484 : if (prog) {
1249 13482 : glUseProgram(prog->prog);
1250 : GL_CHECK_ERR()
1251 13482 : tx_bind_with_mode(txh, txh->transparent, txh->tx_io->blend_mode, 0, prog->prog);
1252 : } else
1253 : #endif
1254 : {
1255 2 : tx_bind(txh);
1256 : }
1257 :
1258 13484 : gf_rmt_end_gl();
1259 13484 : glGetError();
1260 13484 : return 1;
1261 :
1262 : }
1263 :
1264 14334 : u32 gf_sc_texture_enable(GF_TextureHandler *txh, GF_Node *tx_transform)
1265 : {
1266 14334 : return gf_sc_texture_enable_ex(txh, tx_transform, NULL);
1267 : }
1268 :
1269 :
1270 : #endif
1271 :
1272 0 : Bool gf_sc_texture_needs_reload(GF_TextureHandler *txh)
1273 : {
1274 589 : return (txh->tx_io->flags & TX_NEEDS_HW_LOAD) ? 1 : 0;
1275 : }
1276 :
1277 :
1278 34377 : GF_EVGStencil * gf_sc_texture_get_stencil(GF_TextureHandler *txh)
1279 : {
1280 34377 : return txh->tx_io->tx_raster;
1281 : }
1282 :
1283 3229 : void gf_sc_texture_set_stencil(GF_TextureHandler *txh, GF_EVGStencil * stencil)
1284 : {
1285 3229 : txh->tx_io->tx_raster = stencil;
1286 3229 : txh->tx_io->flags |= TX_NEEDS_HW_LOAD;
1287 3229 : }
1288 :
1289 64737 : void gf_sc_texture_check_pause_on_first_load(GF_TextureHandler *txh, Bool do_freeze)
1290 : {
1291 64737 : if (!txh->stream || !txh->tx_io)
1292 : return;
1293 :
1294 20604 : if (do_freeze) {
1295 7304 : if (! (txh->tx_io->flags & TX_FIRST_UPLOAD_FREEZE) ) {
1296 313 : txh->tx_io->flags |= TX_FIRST_UPLOAD_FREEZE;
1297 313 : gf_sc_ar_control(txh->compositor->audio_renderer, GF_SC_AR_PAUSE);
1298 : }
1299 : } else {
1300 13300 : if (!(txh->tx_io->flags & TX_FIRST_UPLOAD_FREEZE_DONE)) {
1301 313 : txh->tx_io->flags |= TX_FIRST_UPLOAD_FREEZE_DONE;
1302 313 : gf_sc_ar_control(txh->compositor->audio_renderer, GF_SC_AR_RESUME);
1303 : }
1304 : }
1305 : }
1306 :
|