📄 texturing_gl.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / 3D rendering module * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "render3d_nodes.h"#include "gl_inc.h"/*tx flags*/enum{ /*these 4 are exclusives*/ TX_MUST_SCALE = (1<<1), TX_IS_POW2 = (1<<2), TX_IS_RECT = (1<<3), TX_EMULE_POW2 = (1<<4), /*signal video data must be sent to hw*/ TX_NEEDS_HW_LOAD = (1<<5),};typedef struct{ /*opengl texture id*/ u32 id; /*tx type*/ u32 tx_flags; u32 blend_mode; Bool first_load; u32 rescale_width, rescale_height; char *scale_data; char *conv_data; Fixed conv_wscale, conv_hscale; u32 conv_format, conv_w, conv_h; /*gl textures vars (gl_type: 2D texture or rectangle (NV ext) )*/ u32 nb_comp, gl_format, gl_type;} GLTexture;GF_Err tx_allocate(GF_TextureHandler *txh){ GLTexture *gltx; if (txh->hwtx) return GF_OK; gltx = (GLTexture*)malloc(sizeof(GLTexture)); if (!gltx) return GF_OUT_OF_MEM; txh->hwtx = gltx; memset(gltx, 0, sizeof(GLTexture)); glGenTextures(1, &gltx->id); if (!gltx->id) return GF_IO_ERR; gltx->first_load = 1; return GF_OK;}void tx_delete(GF_TextureHandler *txh){ if (txh->hwtx) { GLTexture *gltx = (GLTexture *) txh->hwtx; if (gltx->id) glDeleteTextures(1, &gltx->id); if (gltx->scale_data) free(gltx->scale_data); if (gltx->conv_data) free(gltx->conv_data); free(gltx); txh->hwtx = NULL; }}void tx_set_blend_mode(GF_TextureHandler *txh, u32 mode){ if (txh->hwtx) { GLTexture *gltx = (GLTexture *) txh->hwtx; if (gltx) gltx->blend_mode = mode; }}void tx_bind_with_mode(GF_TextureHandler *txh, Bool transparent, u32 blend_mode){ GLTexture *gltx = (GLTexture *) txh->hwtx; if (!gltx->id || !gltx->gl_type) return; glEnable(gltx->gl_type); switch (blend_mode) { case TX_BLEND: if (txh->transparent) glEnable(GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); break; case TX_REPLACE: if (txh->transparent) glEnable(GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); break; case TX_MODULATE: if (txh->transparent) glEnable(GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); break; case TX_DECAL: default: if ((gltx->gl_format==GL_LUMINANCE) || (gltx->gl_format==GL_LUMINANCE_ALPHA)) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND/*GL_MODULATE*/); } else { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); } break; } glBindTexture(gltx->gl_type, gltx->id);}void tx_bind(GF_TextureHandler *txh){ GLTexture *gltx = (GLTexture *) txh->hwtx; tx_bind_with_mode(txh, txh->transparent, gltx->blend_mode);}void tx_disable(GF_TextureHandler *txh){ GLTexture *gltx; if (txh && txh->hwtx) { gltx = (GLTexture *) txh->hwtx; glDisable(gltx->gl_type); if (txh->transparent) glDisable(GL_BLEND); }}u32 get_pow2(u32 s){ u32 i; u32 res = s; u32 sizes[] = { 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 }; u32 nSizes = sizeof(sizes) / sizeof(int); for (i = 0; i < nSizes; ++i) { if (res <= sizes[i]) { res = sizes[i]; break; } } return res;}Bool tx_can_use_rect_ext(Render3D *sr, GF_TextureHandler *txh){ u32 i, count; if (!sr->hw_caps.rect_texture) return 0; if (!sr->disable_rect_ext) return 1; /*this happens ONLY with text texturing*/ if (!txh->owner) return 0; count = gf_node_get_parent_count(txh->owner); /*background 2D can use RECT ext without pb*/ if (gf_node_get_tag(txh->owner)==TAG_MPEG4_Background2D) return 1; /*if a bitmap is using the texture force using RECT*/ for (i=0; i<count; i++) { GF_Node *n = gf_node_get_parent(txh->owner, 0); if (gf_node_get_tag(n)==TAG_MPEG4_Appearance) { count = gf_node_get_parent_count(n); for (i=0; i<count; i++) { M_Shape *s = (M_Shape *) gf_node_get_parent(n, 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; } } } return 0;}Bool tx_setup_format(GF_TextureHandler *txh){ Bool is_pow2, use_rect; Render3D *sr = (Render3D *)txh->compositor->visual_renderer->user_priv; GLTexture *gltx = (GLTexture *) txh->hwtx; /*first setup, this will force recompute bounds in case used with bitmap - we could refine and only invalidate for bitmaps only*/ if (txh->owner && (!gltx->rescale_width || !gltx->rescale_height)) gf_node_dirty_set(txh->owner, 0, 1); gltx->rescale_width = get_pow2(txh->width); gltx->rescale_height = get_pow2(txh->height); is_pow2 = ((gltx->rescale_width==txh->width) && (gltx->rescale_height==txh->height)) ? 1 : 0; gltx->tx_flags = TX_IS_POW2; gltx->gl_type = GL_TEXTURE_2D; use_rect = tx_can_use_rect_ext(sr, txh); if (!is_pow2 && use_rect) { gltx->gl_type = GL_TEXTURE_RECTANGLE_EXT; gltx->tx_flags = TX_IS_RECT; } if (!use_rect && !sr->hw_caps.npot_texture && !is_pow2) gltx->tx_flags = TX_MUST_SCALE; gltx->nb_comp = gltx->gl_format = 0; switch (txh->pixelformat) { case GF_PIXEL_GREYSCALE: gltx->gl_format = GL_LUMINANCE; gltx->nb_comp = 1; gltx->gl_type = GL_TEXTURE_2D; if (!is_pow2) gltx->tx_flags = TX_MUST_SCALE; break; case GF_PIXEL_ALPHAGREY: gltx->gl_format = GL_LUMINANCE_ALPHA; gltx->nb_comp = 2; gltx->gl_type = GL_TEXTURE_2D; if (!is_pow2) gltx->tx_flags = TX_MUST_SCALE; break; case GF_PIXEL_RGB_24: gltx->gl_format = GL_RGB; gltx->nb_comp = 3; break; case GF_PIXEL_RGB_32: case GF_PIXEL_RGBA: gltx->gl_format = GL_RGBA; gltx->nb_comp = 4; break; case GF_PIXEL_ARGB: if (!sr->hw_caps.bgra_texture) return 0; gltx->gl_format = GL_BGRA_EXT; gltx->nb_comp = 4; break; case GF_PIXEL_YV12: if (!use_rect && sr->emul_pow2) gltx->tx_flags = TX_EMULE_POW2; gltx->gl_format = GL_RGB; gltx->nb_comp = 3; break; default: return 0; } /*note we don't free the data if existing, since this only happen when re-setting up after context loss (same size)*/ if ((gltx->tx_flags == TX_MUST_SCALE) & !gltx->scale_data) gltx->scale_data = (char*)malloc(sizeof(char) * gltx->nb_comp*gltx->rescale_width*gltx->rescale_height); glEnable(gltx->gl_type); glBindTexture(gltx->gl_type, gltx->id);#ifdef GPAC_USE_OGL_ES glTexParameterx(gltx->gl_type, GL_TEXTURE_WRAP_S, (txh->flags & GF_SR_TEXTURE_REPEAT_S) ? GL_REPEAT : GL_CLAMP_TO_EDGE); glTexParameterx(gltx->gl_type, GL_TEXTURE_WRAP_T, (txh->flags & GF_SR_TEXTURE_REPEAT_T) ? GL_REPEAT : GL_CLAMP_TO_EDGE); if (gltx->gl_type == GL_TEXTURE_2D) { glTexParameterx(gltx->gl_type, GL_TEXTURE_MAG_FILTER, txh->compositor->high_speed ? GL_NEAREST : GL_LINEAR); glTexParameterx(gltx->gl_type, GL_TEXTURE_MIN_FILTER, txh->compositor->high_speed ? GL_NEAREST : GL_LINEAR); } else { glTexParameterx(gltx->gl_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterx(gltx->gl_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR); }#else glTexParameteri(gltx->gl_type, GL_TEXTURE_WRAP_S, (txh->flags & GF_SR_TEXTURE_REPEAT_S) ? GL_REPEAT : GL_CLAMP); glTexParameteri(gltx->gl_type, GL_TEXTURE_WRAP_T, (txh->flags & GF_SR_TEXTURE_REPEAT_T) ? GL_REPEAT : GL_CLAMP); if (gltx->gl_type == GL_TEXTURE_2D) { glTexParameteri(gltx->gl_type, GL_TEXTURE_MAG_FILTER, txh->compositor->high_speed ? GL_NEAREST : GL_LINEAR); glTexParameteri(gltx->gl_type, GL_TEXTURE_MIN_FILTER, txh->compositor->high_speed ? GL_NEAREST : GL_LINEAR); } else { glTexParameteri(gltx->gl_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(gltx->gl_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR); }#endif glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glDisable(gltx->gl_type); gltx->first_load = 1; return 1;}char *tx_get_data(GF_TextureHandler *txh, u32 *pix_format){ GLTexture *gltx = (GLTexture *) txh->hwtx; char *data = gltx->conv_data; *pix_format = gltx->conv_format; if (*pix_format == txh->pixelformat) data = txh->data; return data;}u32 get_next_pow2(u32 s){ u32 i; u32 res = s; u32 sizes[] = { 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 }; u32 nSizes = sizeof(sizes) / sizeof(int); for (i = 0; i < nSizes; ++i) { if (res <= sizes[i]) { res = sizes[i]; break; } } return res;}/*note about conversion: we consider that a texture without a stream attached is generated by the rendererhence is never flipped. Otherwise all textures attached to stream are flipped in order to match uv coords*/Bool tx_convert(GF_TextureHandler *txh){ GF_VideoSurface src, dst; u32 out_stride; GLTexture *gltx = (GLTexture *) txh->hwtx; Render3D *sr = (Render3D *)txh->compositor->visual_renderer->user_priv; switch (txh->pixelformat) { case GF_PIXEL_ARGB: if (!sr->hw_caps.bgra_texture) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -