LCOV - code coverage report
Current view: top level - compositor - texturing_gl.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 301 536 56.2 %
Date: 2021-04-29 23:48:07 Functions: 25 29 86.2 %

          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             : 

Generated by: LCOV version 1.13