material: Avoid redundant glBindTexture calls
This adds a _cogl_bind_gl_texture_transient function that should be used instead of glBindTexture so we can have a consistent cache of the textures bound to each texture unit so we can avoid some redundant binding.
This commit is contained in:
parent
acc44161c1
commit
82e80e6765
@ -146,7 +146,9 @@ _cogl_atlas_texture_blit_begin (CoglAtlasTextureBlitData *data,
|
|||||||
data->fbo = 0;
|
data->fbo = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GE( glBindTexture (data->dst_gl_target, dst_gl_texture) );
|
_cogl_bind_gl_texture_transient (data->dst_gl_target,
|
||||||
|
dst_gl_texture,
|
||||||
|
FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->fbo)
|
if (data->fbo)
|
||||||
@ -274,7 +276,8 @@ _cogl_atlas_texture_free (CoglAtlasTexture *atlas_tex)
|
|||||||
|
|
||||||
cogl_handle_unref (atlas_tex->sub_texture);
|
cogl_handle_unref (atlas_tex->sub_texture);
|
||||||
|
|
||||||
g_free (atlas_tex);
|
/* Chain up */
|
||||||
|
_cogl_texture_free (COGL_TEXTURE (atlas_tex));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1074,5 +1077,6 @@ cogl_atlas_texture_vtable =
|
|||||||
_cogl_atlas_texture_get_format,
|
_cogl_atlas_texture_get_format,
|
||||||
_cogl_atlas_texture_get_gl_format,
|
_cogl_atlas_texture_get_gl_format,
|
||||||
_cogl_atlas_texture_get_width,
|
_cogl_atlas_texture_get_width,
|
||||||
_cogl_atlas_texture_get_height
|
_cogl_atlas_texture_get_height,
|
||||||
|
NULL /* is_foreign */
|
||||||
};
|
};
|
||||||
|
@ -70,6 +70,26 @@ typedef struct _CoglTextureUnit
|
|||||||
* with a layer may represent more than one GL texture) */
|
* with a layer may represent more than one GL texture) */
|
||||||
GLuint gl_texture;
|
GLuint gl_texture;
|
||||||
|
|
||||||
|
/* Foreign textures are those not created or deleted by Cogl. If we ever
|
||||||
|
* call glBindTexture for a foreign texture then the next time we are
|
||||||
|
* asked to glBindTexture we can't try and optimize a redundant state
|
||||||
|
* change because we don't know if the original texture name was deleted
|
||||||
|
* and now we are being asked to bind a recycled name. */
|
||||||
|
gboolean is_foreign;
|
||||||
|
|
||||||
|
/* We have many components in Cogl that need to temporarily bind arbitrary
|
||||||
|
* textures e.g. to query texture object parameters and since we don't
|
||||||
|
* want that to result in too much redundant reflushing of layer state
|
||||||
|
* when all that's needed is to re-bind the layers gl_texture we use this
|
||||||
|
* to track when the .layer_gl_texture state is invalid.
|
||||||
|
*
|
||||||
|
* XXX: as a further optimization cogl-material.c uses a convention
|
||||||
|
* of always leaving texture unit 1 active when not dealing with the
|
||||||
|
* flushing of layer state, so we can assume this is only ever TRUE
|
||||||
|
* for unit 1.
|
||||||
|
*/
|
||||||
|
gboolean dirty_gl_texture;
|
||||||
|
|
||||||
/* A matrix stack giving us the means to associate a texture
|
/* A matrix stack giving us the means to associate a texture
|
||||||
* transform matrix with the texture unit. */
|
* transform matrix with the texture unit. */
|
||||||
CoglMatrixStack *matrix_stack;
|
CoglMatrixStack *matrix_stack;
|
||||||
@ -123,6 +143,11 @@ _cogl_get_texture_unit (int index_);
|
|||||||
void
|
void
|
||||||
_cogl_destroy_texture_units (void);
|
_cogl_destroy_texture_units (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_bind_gl_texture_transient (GLenum gl_target,
|
||||||
|
GLuint gl_texture,
|
||||||
|
gboolean is_foreign);
|
||||||
|
|
||||||
typedef enum _CoglMaterialEqualFlags
|
typedef enum _CoglMaterialEqualFlags
|
||||||
{
|
{
|
||||||
/* Return FALSE if any component of either material isn't set to its
|
/* Return FALSE if any component of either material isn't set to its
|
||||||
@ -440,6 +465,9 @@ void
|
|||||||
_cogl_material_set_user_program (CoglHandle handle,
|
_cogl_material_set_user_program (CoglHandle handle,
|
||||||
CoglHandle program);
|
CoglHandle program);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_delete_gl_texture (GLuint gl_texture);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_material_apply_legacy_state (CoglHandle handle);
|
_cogl_material_apply_legacy_state (CoglHandle handle);
|
||||||
|
|
||||||
|
@ -962,6 +962,8 @@ texture_unit_init (CoglTextureUnit *unit, int index_)
|
|||||||
unit->enabled = FALSE;
|
unit->enabled = FALSE;
|
||||||
unit->enabled_gl_target = 0;
|
unit->enabled_gl_target = 0;
|
||||||
unit->gl_texture = 0;
|
unit->gl_texture = 0;
|
||||||
|
unit->is_foreign = FALSE;
|
||||||
|
unit->dirty_gl_texture = FALSE;
|
||||||
unit->matrix_stack = _cogl_matrix_stack_new ();
|
unit->matrix_stack = _cogl_matrix_stack_new ();
|
||||||
|
|
||||||
unit->layer = NULL;
|
unit->layer = NULL;
|
||||||
@ -1027,6 +1029,71 @@ set_active_texture_unit (int unit_index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note: this conceptually has slightly different semantics to
|
||||||
|
* OpenGL's glBindTexture because Cogl never cares about tracking
|
||||||
|
* multiple textures bound to different targets on the same texture
|
||||||
|
* unit.
|
||||||
|
*
|
||||||
|
* glBindTexture lets you bind multiple textures to a single texture
|
||||||
|
* unit if they are bound to different targets. So it does something
|
||||||
|
* like:
|
||||||
|
* unit->current_texture[target] = texture;
|
||||||
|
*
|
||||||
|
* Cogl only lets you associate one texture with the currently active
|
||||||
|
* texture unit, so the target is basically a redundant parameter
|
||||||
|
* that's implicitly set on that texture.
|
||||||
|
*
|
||||||
|
* Technically this is just a thin wrapper around glBindTexture so
|
||||||
|
* actually it does have the GL semantics but it seems worth
|
||||||
|
* mentioning the conceptual difference in case anyone wonders why we
|
||||||
|
* don't associate the gl_texture with a gl_target in the
|
||||||
|
* CoglTextureUnit.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_cogl_bind_gl_texture_transient (GLenum gl_target,
|
||||||
|
GLuint gl_texture,
|
||||||
|
gboolean is_foreign)
|
||||||
|
{
|
||||||
|
CoglTextureUnit *unit;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
unit = _cogl_get_texture_unit (ctx->active_texture_unit);
|
||||||
|
|
||||||
|
/* NB: If we have previously bound a foreign texture to this texture
|
||||||
|
* unit we don't know if that texture has since been deleted and we
|
||||||
|
* are seeing the texture name recycled */
|
||||||
|
if (unit->gl_texture == gl_texture &&
|
||||||
|
!unit->dirty_gl_texture &&
|
||||||
|
!unit->is_foreign)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GE (glBindTexture (gl_target, gl_texture));
|
||||||
|
|
||||||
|
unit->dirty_gl_texture = TRUE;
|
||||||
|
unit->is_foreign = is_foreign;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_delete_gl_texture (GLuint gl_texture)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
for (i = 0; i < ctx->texture_units->len; i++)
|
||||||
|
{
|
||||||
|
CoglTextureUnit *unit =
|
||||||
|
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
|
||||||
|
|
||||||
|
if (unit->gl_texture == gl_texture)
|
||||||
|
{
|
||||||
|
unit->gl_texture = 0;
|
||||||
|
unit->dirty_gl_texture = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Asserts that a layer corresponding to the given index exists. If no
|
/* Asserts that a layer corresponding to the given index exists. If no
|
||||||
* match is found, then a new empty layer is added.
|
* match is found, then a new empty layer is added.
|
||||||
*/
|
*/
|
||||||
@ -2926,14 +2993,42 @@ _cogl_material_flush_common_gl_state (CoglMaterial *material,
|
|||||||
unit->layer0_overridden = layer0_override_texture ? TRUE : FALSE;
|
unit->layer0_overridden = layer0_override_texture ? TRUE : FALSE;
|
||||||
unit->fallback = fallback;
|
unit->fallback = fallback;
|
||||||
|
|
||||||
/* FIXME: We could be more clever here and only bind the texture
|
/* NB: There are several Cogl components and some code in
|
||||||
if it is different from gl_layer_info->gl_texture to avoid
|
* Clutter that will temporarily bind arbitrary GL textures to
|
||||||
redundant GL calls. However a few other places in Cogl and
|
* query and modify texture object parameters. If you look at
|
||||||
Clutter call glBindTexture such as ClutterGLXTexturePixmap so
|
* the end of _cogl_material_flush_gl_state() you can see we
|
||||||
we'd need to ensure they affect the cache. Also deleting a
|
* make sure that such code always binds to texture unit 1 by
|
||||||
texture should clear it from the cache in case a new texture
|
* always leaving texture unit 1 active. This means we can't
|
||||||
is generated with the same number */
|
* rely on the unit->gl_texture state if unit->index == 1.
|
||||||
|
* Because texture unit 1 is a bit special we actually defer any
|
||||||
|
* necessary glBindTexture for it until the end of
|
||||||
|
* _cogl_material_flush_gl_state().
|
||||||
|
*
|
||||||
|
* NB: we get notified whenever glDeleteTextures is used (see
|
||||||
|
* _cogl_delete_gl_texture()) where we invalidate
|
||||||
|
* unit->gl_texture references to deleted textures so it's safe
|
||||||
|
* to compare unit->gl_texture with gl_texture. (Without the
|
||||||
|
* hook it would be possible to delete a GL texture and create a
|
||||||
|
* new one with the same name and comparing unit->gl_texture and
|
||||||
|
* gl_texture wouldn't detect that.)
|
||||||
|
*
|
||||||
|
* NB: for foreign textures we don't know how the deletion of
|
||||||
|
* the GL texture objects correspond to the deletion of the
|
||||||
|
* CoglTextures so if there was previously a foreign texture
|
||||||
|
* associated with the texture unit then we can't assume that we
|
||||||
|
* aren't seeing a recycled texture name so we have to bind.
|
||||||
|
*/
|
||||||
|
#ifndef DISABLE_MATERIAL_CACHE
|
||||||
|
if (unit->gl_texture != gl_texture || unit->is_foreign)
|
||||||
|
{
|
||||||
|
if (unit->index != 1)
|
||||||
|
GE (glBindTexture (gl_target, gl_texture));
|
||||||
|
unit->gl_texture = gl_texture;
|
||||||
|
}
|
||||||
|
#else
|
||||||
GE (glBindTexture (gl_target, gl_texture));
|
GE (glBindTexture (gl_target, gl_texture));
|
||||||
|
#endif
|
||||||
|
unit->is_foreign = _cogl_texture_is_foreign (texture);
|
||||||
|
|
||||||
/* Disable the previous target if it was different and it's
|
/* Disable the previous target if it was different and it's
|
||||||
* still enabled */
|
* still enabled */
|
||||||
@ -3275,10 +3370,11 @@ done: /* well, almost... */
|
|||||||
* unless multitexturing is being used.
|
* unless multitexturing is being used.
|
||||||
*/
|
*/
|
||||||
unit1 = _cogl_get_texture_unit (1);
|
unit1 = _cogl_get_texture_unit (1);
|
||||||
if (unit1->enabled)
|
if (unit1->enabled && unit1->dirty_gl_texture)
|
||||||
{
|
{
|
||||||
set_active_texture_unit (1);
|
set_active_texture_unit (1);
|
||||||
GE (glBindTexture (unit1->enabled_gl_target, unit1->gl_texture));
|
GE (glBindTexture (unit1->enabled_gl_target, unit1->gl_texture));
|
||||||
|
unit1->dirty_gl_texture = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Since there are several places where Cogl will temporarily bind a
|
/* Since there are several places where Cogl will temporarily bind a
|
||||||
|
@ -243,7 +243,8 @@ _cogl_sub_texture_free (CoglSubTexture *sub_tex)
|
|||||||
cogl_handle_unref (sub_tex->next_texture);
|
cogl_handle_unref (sub_tex->next_texture);
|
||||||
cogl_handle_unref (sub_tex->full_texture);
|
cogl_handle_unref (sub_tex->full_texture);
|
||||||
|
|
||||||
g_free (sub_tex);
|
/* Chain up */
|
||||||
|
_cogl_texture_free (COGL_TEXTURE (sub_tex));
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
@ -556,5 +557,6 @@ cogl_sub_texture_vtable =
|
|||||||
_cogl_sub_texture_get_format,
|
_cogl_sub_texture_get_format,
|
||||||
_cogl_sub_texture_get_gl_format,
|
_cogl_sub_texture_get_gl_format,
|
||||||
_cogl_sub_texture_get_width,
|
_cogl_sub_texture_get_width,
|
||||||
_cogl_sub_texture_get_height
|
_cogl_sub_texture_get_height,
|
||||||
|
NULL /* is_foreign */
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "cogl-handle.h"
|
#include "cogl-handle.h"
|
||||||
#include "cogl-spans.h"
|
#include "cogl-spans.h"
|
||||||
#include "cogl-journal-private.h"
|
#include "cogl-journal-private.h"
|
||||||
|
#include "cogl-material-private.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -253,6 +254,7 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
_cogl_texture_driver_upload_subregion_to_gl (
|
_cogl_texture_driver_upload_subregion_to_gl (
|
||||||
tex_2ds->gl_target,
|
tex_2ds->gl_target,
|
||||||
gl_handle,
|
gl_handle,
|
||||||
|
tex_2ds->is_foreign,
|
||||||
x_span->start, /* src x */
|
x_span->start, /* src x */
|
||||||
y_span->start, /* src y */
|
y_span->start, /* src y */
|
||||||
0, /* dst x */
|
0, /* dst x */
|
||||||
@ -441,6 +443,7 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
|
|
||||||
_cogl_texture_driver_upload_subregion_to_gl (tex_2ds->gl_target,
|
_cogl_texture_driver_upload_subregion_to_gl (tex_2ds->gl_target,
|
||||||
gl_handle,
|
gl_handle,
|
||||||
|
tex_2ds->is_foreign,
|
||||||
source_x,
|
source_x,
|
||||||
source_y,
|
source_y,
|
||||||
local_x, /* dst x */
|
local_x, /* dst x */
|
||||||
@ -680,7 +683,9 @@ _cogl_texture_2d_sliced_set_wrap_mode_parameters (CoglTexture *tex,
|
|||||||
{
|
{
|
||||||
GLuint texnum = g_array_index (tex_2ds->slice_gl_handles, GLuint, i);
|
GLuint texnum = g_array_index (tex_2ds->slice_gl_handles, GLuint, i);
|
||||||
|
|
||||||
GE( glBindTexture (tex_2ds->gl_target, texnum) );
|
_cogl_bind_gl_texture_transient (tex_2ds->gl_target,
|
||||||
|
texnum,
|
||||||
|
tex_2ds->is_foreign);
|
||||||
GE( glTexParameteri (tex_2ds->gl_target,
|
GE( glTexParameteri (tex_2ds->gl_target,
|
||||||
GL_TEXTURE_WRAP_S, wrap_mode_s) );
|
GL_TEXTURE_WRAP_S, wrap_mode_s) );
|
||||||
GE( glTexParameteri (tex_2ds->gl_target,
|
GE( glTexParameteri (tex_2ds->gl_target,
|
||||||
@ -855,8 +860,9 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds,
|
|||||||
y_span->size - y_span->waste);
|
y_span->size - y_span->waste);
|
||||||
|
|
||||||
/* Setup texture parameters */
|
/* Setup texture parameters */
|
||||||
GE( glBindTexture (tex_2ds->gl_target,
|
_cogl_bind_gl_texture_transient (tex_2ds->gl_target,
|
||||||
gl_handles[y * n_x_slices + x] ) );
|
gl_handles[y * n_x_slices + x],
|
||||||
|
FALSE);
|
||||||
|
|
||||||
_cogl_texture_driver_try_setting_gl_border_color (tex_2ds->gl_target,
|
_cogl_texture_driver_try_setting_gl_border_color (tex_2ds->gl_target,
|
||||||
transparent_color);
|
transparent_color);
|
||||||
@ -882,11 +888,14 @@ _cogl_texture_2d_sliced_slices_free (CoglTexture2DSliced *tex_2ds)
|
|||||||
|
|
||||||
if (tex_2ds->slice_gl_handles != NULL)
|
if (tex_2ds->slice_gl_handles != NULL)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
if (tex_2ds->is_foreign == FALSE)
|
if (tex_2ds->is_foreign == FALSE)
|
||||||
{
|
for (i = 0; i < tex_2ds->slice_gl_handles->len; i++)
|
||||||
GE( glDeleteTextures (tex_2ds->slice_gl_handles->len,
|
{
|
||||||
(GLuint*) tex_2ds->slice_gl_handles->data) );
|
GLuint texture =
|
||||||
}
|
g_array_index (tex_2ds->slice_gl_handles, GLuint, i);
|
||||||
|
_cogl_delete_gl_texture (texture);
|
||||||
|
}
|
||||||
|
|
||||||
g_array_free (tex_2ds->slice_gl_handles, TRUE);
|
g_array_free (tex_2ds->slice_gl_handles, TRUE);
|
||||||
}
|
}
|
||||||
@ -899,7 +908,9 @@ static void
|
|||||||
_cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds)
|
_cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds)
|
||||||
{
|
{
|
||||||
_cogl_texture_2d_sliced_slices_free (tex_2ds);
|
_cogl_texture_2d_sliced_slices_free (tex_2ds);
|
||||||
g_free (tex_2ds);
|
|
||||||
|
/* Chain up */
|
||||||
|
_cogl_texture_free (COGL_TEXTURE (tex_2ds));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -1121,7 +1132,8 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle,
|
|||||||
/* Make sure binding succeeds */
|
/* Make sure binding succeeds */
|
||||||
while ((gl_error = glGetError ()) != GL_NO_ERROR)
|
while ((gl_error = glGetError ()) != GL_NO_ERROR)
|
||||||
;
|
;
|
||||||
glBindTexture (gl_target, gl_handle);
|
|
||||||
|
_cogl_bind_gl_texture_transient (gl_target, gl_handle, TRUE);
|
||||||
if (glGetError () != GL_NO_ERROR)
|
if (glGetError () != GL_NO_ERROR)
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
@ -1226,6 +1238,12 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle,
|
|||||||
return _cogl_texture_2d_sliced_handle_new (tex_2ds);
|
return _cogl_texture_2d_sliced_handle_new (tex_2ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_cogl_texture_2d_sliced_is_foreign (CoglTexture *tex)
|
||||||
|
{
|
||||||
|
return COGL_TEXTURE_2D_SLICED (tex)->is_foreign;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_cogl_texture_2d_sliced_get_max_waste (CoglTexture *tex)
|
_cogl_texture_2d_sliced_get_max_waste (CoglTexture *tex)
|
||||||
{
|
{
|
||||||
@ -1371,7 +1389,9 @@ _cogl_texture_2d_sliced_set_filters (CoglTexture *tex,
|
|||||||
for (i=0; i<tex_2ds->slice_gl_handles->len; ++i)
|
for (i=0; i<tex_2ds->slice_gl_handles->len; ++i)
|
||||||
{
|
{
|
||||||
gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, i);
|
gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, i);
|
||||||
GE( glBindTexture (tex_2ds->gl_target, gl_handle) );
|
_cogl_bind_gl_texture_transient (tex_2ds->gl_target,
|
||||||
|
gl_handle,
|
||||||
|
tex_2ds->is_foreign);
|
||||||
GE( glTexParameteri (tex_2ds->gl_target, GL_TEXTURE_MAG_FILTER,
|
GE( glTexParameteri (tex_2ds->gl_target, GL_TEXTURE_MAG_FILTER,
|
||||||
tex_2ds->mag_filter) );
|
tex_2ds->mag_filter) );
|
||||||
GE( glTexParameteri (tex_2ds->gl_target, GL_TEXTURE_MIN_FILTER,
|
GE( glTexParameteri (tex_2ds->gl_target, GL_TEXTURE_MIN_FILTER,
|
||||||
@ -1399,7 +1419,9 @@ _cogl_texture_2d_sliced_ensure_mipmaps (CoglTexture *tex)
|
|||||||
for (i = 0; i < tex_2ds->slice_gl_handles->len; i++)
|
for (i = 0; i < tex_2ds->slice_gl_handles->len; i++)
|
||||||
{
|
{
|
||||||
GLuint gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, i);
|
GLuint gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, i);
|
||||||
GE( glBindTexture (tex_2ds->gl_target, gl_handle) );
|
_cogl_bind_gl_texture_transient (tex_2ds->gl_target,
|
||||||
|
gl_handle,
|
||||||
|
tex_2ds->is_foreign);
|
||||||
|
|
||||||
/* glGenerateMipmap is defined in the FBO extension */
|
/* glGenerateMipmap is defined in the FBO extension */
|
||||||
if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||||
@ -1544,7 +1566,9 @@ _cogl_texture_2d_sliced_download_from_gl (
|
|||||||
bpp);
|
bpp);
|
||||||
|
|
||||||
/* Download slice image data into temp bmp */
|
/* Download slice image data into temp bmp */
|
||||||
GE( glBindTexture (tex_2ds->gl_target, gl_handle) );
|
_cogl_bind_gl_texture_transient (tex_2ds->gl_target,
|
||||||
|
gl_handle,
|
||||||
|
tex_2ds->is_foreign);
|
||||||
|
|
||||||
if (!_cogl_texture_driver_gl_get_tex_image (tex_2ds->gl_target,
|
if (!_cogl_texture_driver_gl_get_tex_image (tex_2ds->gl_target,
|
||||||
target_gl_format,
|
target_gl_format,
|
||||||
@ -1578,7 +1602,9 @@ _cogl_texture_2d_sliced_download_from_gl (
|
|||||||
bpp);
|
bpp);
|
||||||
|
|
||||||
/* Download slice image data */
|
/* Download slice image data */
|
||||||
GE( glBindTexture (tex_2ds->gl_target, gl_handle) );
|
_cogl_bind_gl_texture_transient (tex_2ds->gl_target,
|
||||||
|
gl_handle,
|
||||||
|
tex_2ds->is_foreign);
|
||||||
|
|
||||||
if (!_cogl_texture_driver_gl_get_tex_image (tex_2ds->gl_target,
|
if (!_cogl_texture_driver_gl_get_tex_image (tex_2ds->gl_target,
|
||||||
target_gl_format,
|
target_gl_format,
|
||||||
@ -1737,5 +1763,6 @@ cogl_texture_2d_sliced_vtable =
|
|||||||
_cogl_texture_2d_sliced_get_format,
|
_cogl_texture_2d_sliced_get_format,
|
||||||
_cogl_texture_2d_sliced_get_gl_format,
|
_cogl_texture_2d_sliced_get_gl_format,
|
||||||
_cogl_texture_2d_sliced_get_width,
|
_cogl_texture_2d_sliced_get_width,
|
||||||
_cogl_texture_2d_sliced_get_height
|
_cogl_texture_2d_sliced_get_height,
|
||||||
|
_cogl_texture_2d_sliced_is_foreign
|
||||||
};
|
};
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "cogl-context.h"
|
#include "cogl-context.h"
|
||||||
#include "cogl-handle.h"
|
#include "cogl-handle.h"
|
||||||
#include "cogl-journal-private.h"
|
#include "cogl-journal-private.h"
|
||||||
|
#include "cogl-material-private.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@ -137,7 +138,9 @@ _cogl_texture_2d_set_wrap_mode_parameters (CoglTexture *tex,
|
|||||||
if (tex_2d->wrap_mode_s != wrap_mode_s ||
|
if (tex_2d->wrap_mode_s != wrap_mode_s ||
|
||||||
tex_2d->wrap_mode_t != wrap_mode_t)
|
tex_2d->wrap_mode_t != wrap_mode_t)
|
||||||
{
|
{
|
||||||
GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) );
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
||||||
|
tex_2d->gl_texture,
|
||||||
|
FALSE);
|
||||||
GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode_s) );
|
GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode_s) );
|
||||||
GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode_t) );
|
GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode_t) );
|
||||||
|
|
||||||
@ -149,8 +152,10 @@ _cogl_texture_2d_set_wrap_mode_parameters (CoglTexture *tex,
|
|||||||
static void
|
static void
|
||||||
_cogl_texture_2d_free (CoglTexture2D *tex_2d)
|
_cogl_texture_2d_free (CoglTexture2D *tex_2d)
|
||||||
{
|
{
|
||||||
GE( glDeleteTextures (1, &tex_2d->gl_texture) );
|
_cogl_delete_gl_texture (tex_2d->gl_texture);
|
||||||
g_free (tex_2d);
|
|
||||||
|
/* Chain up */
|
||||||
|
_cogl_texture_free (COGL_TEXTURE (tex_2d));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -253,7 +258,9 @@ _cogl_texture_2d_new_with_size (unsigned int width,
|
|||||||
tex_2d = _cogl_texture_2d_create_base (width, height, flags, internal_format);
|
tex_2d = _cogl_texture_2d_create_base (width, height, flags, internal_format);
|
||||||
|
|
||||||
_cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
|
_cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
|
||||||
GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) );
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
||||||
|
tex_2d->gl_texture,
|
||||||
|
FALSE);
|
||||||
GE( glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
|
GE( glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
|
||||||
width, height, 0, gl_format, gl_type, NULL) );
|
width, height, 0, gl_format, gl_type, NULL) );
|
||||||
|
|
||||||
@ -299,6 +306,7 @@ _cogl_texture_2d_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
_cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
|
_cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
|
||||||
_cogl_texture_driver_upload_to_gl (GL_TEXTURE_2D,
|
_cogl_texture_driver_upload_to_gl (GL_TEXTURE_2D,
|
||||||
tex_2d->gl_texture,
|
tex_2d->gl_texture,
|
||||||
|
FALSE,
|
||||||
&dst_bmp,
|
&dst_bmp,
|
||||||
gl_intformat,
|
gl_intformat,
|
||||||
gl_format,
|
gl_format,
|
||||||
@ -389,7 +397,9 @@ _cogl_texture_2d_set_filters (CoglTexture *tex,
|
|||||||
tex_2d->mag_filter = mag_filter;
|
tex_2d->mag_filter = mag_filter;
|
||||||
|
|
||||||
/* Apply new filters to the texture */
|
/* Apply new filters to the texture */
|
||||||
GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) );
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
||||||
|
tex_2d->gl_texture,
|
||||||
|
FALSE);
|
||||||
GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter) );
|
GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter) );
|
||||||
GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter) );
|
GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter) );
|
||||||
}
|
}
|
||||||
@ -405,7 +415,9 @@ _cogl_texture_2d_ensure_mipmaps (CoglTexture *tex)
|
|||||||
if (!tex_2d->auto_mipmap || !tex_2d->mipmaps_dirty)
|
if (!tex_2d->auto_mipmap || !tex_2d->mipmaps_dirty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) );
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
||||||
|
tex_2d->gl_texture,
|
||||||
|
FALSE);
|
||||||
/* glGenerateMipmap is defined in the FBO extension. We only allow
|
/* glGenerateMipmap is defined in the FBO extension. We only allow
|
||||||
CoglTexture2D instances to be created if this feature is
|
CoglTexture2D instances to be created if this feature is
|
||||||
available so we don't need to check for the extension */
|
available so we don't need to check for the extension */
|
||||||
@ -474,6 +486,7 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
|
|||||||
/* Send data to GL */
|
/* Send data to GL */
|
||||||
_cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_2D,
|
_cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_2D,
|
||||||
tex_2d->gl_texture,
|
tex_2d->gl_texture,
|
||||||
|
FALSE,
|
||||||
src_x, src_y,
|
src_x, src_y,
|
||||||
dst_x, dst_y,
|
dst_x, dst_y,
|
||||||
dst_width, dst_height,
|
dst_width, dst_height,
|
||||||
@ -552,7 +565,9 @@ _cogl_texture_2d_get_data (CoglTexture *tex,
|
|||||||
_cogl_texture_driver_prep_gl_for_pixels_download (target_bmp.rowstride,
|
_cogl_texture_driver_prep_gl_for_pixels_download (target_bmp.rowstride,
|
||||||
closest_bpp);
|
closest_bpp);
|
||||||
|
|
||||||
GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) );
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
||||||
|
tex_2d->gl_texture,
|
||||||
|
FALSE);
|
||||||
if (!_cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_2D,
|
if (!_cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_2D,
|
||||||
closest_gl_format,
|
closest_gl_format,
|
||||||
closest_gl_type,
|
closest_gl_type,
|
||||||
@ -638,5 +653,6 @@ cogl_texture_2d_vtable =
|
|||||||
_cogl_texture_2d_get_format,
|
_cogl_texture_2d_get_format,
|
||||||
_cogl_texture_2d_get_gl_format,
|
_cogl_texture_2d_get_gl_format,
|
||||||
_cogl_texture_2d_get_width,
|
_cogl_texture_2d_get_width,
|
||||||
_cogl_texture_2d_get_height
|
_cogl_texture_2d_get_height,
|
||||||
|
NULL /* is_foreign */
|
||||||
};
|
};
|
||||||
|
@ -61,6 +61,7 @@ _cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride,
|
|||||||
void
|
void
|
||||||
_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
||||||
GLuint gl_handle,
|
GLuint gl_handle,
|
||||||
|
gboolean is_foreign,
|
||||||
int src_x,
|
int src_x,
|
||||||
int src_y,
|
int src_y,
|
||||||
int dst_x,
|
int dst_x,
|
||||||
@ -80,6 +81,7 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
|||||||
void
|
void
|
||||||
_cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
_cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
||||||
GLuint gl_handle,
|
GLuint gl_handle,
|
||||||
|
gboolean is_foreign,
|
||||||
CoglBitmap *source_bmp,
|
CoglBitmap *source_bmp,
|
||||||
GLint internal_gl_format,
|
GLint internal_gl_format,
|
||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
|
@ -118,6 +118,8 @@ struct _CoglTextureVtable
|
|||||||
GLenum (* get_gl_format) (CoglTexture *tex);
|
GLenum (* get_gl_format) (CoglTexture *tex);
|
||||||
int (* get_width) (CoglTexture *tex);
|
int (* get_width) (CoglTexture *tex);
|
||||||
int (* get_height) (CoglTexture *tex);
|
int (* get_height) (CoglTexture *tex);
|
||||||
|
|
||||||
|
gboolean (* is_foreign) (CoglTexture *tex);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _CoglTexture
|
struct _CoglTexture
|
||||||
@ -126,6 +128,20 @@ struct _CoglTexture
|
|||||||
const CoglTextureVtable *vtable;
|
const CoglTextureVtable *vtable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum _CoglTextureChangeFlags
|
||||||
|
{
|
||||||
|
/* Whenever the internals of a texture are changed such that the
|
||||||
|
* underlying GL textures that represent the CoglTexture change then
|
||||||
|
* we notify cogl-material.c via
|
||||||
|
* _cogl_material_texture_pre_change_notify
|
||||||
|
*/
|
||||||
|
COGL_TEXTURE_CHANGE_GL_TEXTURES
|
||||||
|
|
||||||
|
} CoglTextureChangeFlags;
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_texture_free (CoglTexture *texture);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_foreach_sub_texture_in_region (CoglHandle handle,
|
_cogl_texture_foreach_sub_texture_in_region (CoglHandle handle,
|
||||||
float virtual_tx_1,
|
float virtual_tx_1,
|
||||||
@ -215,4 +231,7 @@ _cogl_texture_draw_and_read (CoglHandle handle,
|
|||||||
GLuint target_gl_format,
|
GLuint target_gl_format,
|
||||||
GLuint target_gl_type);
|
GLuint target_gl_type);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_texture_is_foreign (CoglHandle handle);
|
||||||
|
|
||||||
#endif /* __COGL_TEXTURE_PRIVATE_H */
|
#endif /* __COGL_TEXTURE_PRIVATE_H */
|
||||||
|
@ -102,6 +102,12 @@ cogl_texture_unref (CoglHandle handle)
|
|||||||
cogl_handle_unref (handle);
|
cogl_handle_unref (handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_texture_free (CoglTexture *texture)
|
||||||
|
{
|
||||||
|
g_free (texture);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_cogl_texture_needs_premult_conversion (CoglPixelFormat src_format,
|
_cogl_texture_needs_premult_conversion (CoglPixelFormat src_format,
|
||||||
CoglPixelFormat dst_format)
|
CoglPixelFormat dst_format)
|
||||||
@ -471,6 +477,8 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
|||||||
GLuint y_pot_waste,
|
GLuint y_pot_waste,
|
||||||
CoglPixelFormat format)
|
CoglPixelFormat format)
|
||||||
{
|
{
|
||||||
|
/* FIXME: only create a sliced texture if x or y waste was specified
|
||||||
|
*/
|
||||||
return _cogl_texture_2d_sliced_new_from_foreign (gl_handle,
|
return _cogl_texture_2d_sliced_new_from_foreign (gl_handle,
|
||||||
gl_target,
|
gl_target,
|
||||||
width,
|
width,
|
||||||
@ -480,6 +488,21 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
|||||||
format);
|
format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_texture_is_foreign (CoglHandle handle)
|
||||||
|
{
|
||||||
|
CoglTexture *tex;
|
||||||
|
|
||||||
|
g_return_val_if_fail (cogl_is_texture (handle), FALSE);
|
||||||
|
|
||||||
|
tex = COGL_TEXTURE (handle);
|
||||||
|
|
||||||
|
if (tex->vtable->is_foreign)
|
||||||
|
return tex->vtable->is_foreign (tex);
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
cogl_texture_new_from_sub_texture (CoglHandle full_texture,
|
cogl_texture_new_from_sub_texture (CoglHandle full_texture,
|
||||||
int sub_x,
|
int sub_x,
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "cogl-context.h"
|
#include "cogl-context.h"
|
||||||
#include "cogl-handle.h"
|
#include "cogl-handle.h"
|
||||||
#include "cogl-primitives.h"
|
#include "cogl-primitives.h"
|
||||||
|
#include "cogl-material-private.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -58,7 +59,9 @@ _cogl_texture_driver_gen (GLenum gl_target,
|
|||||||
|
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
GE (glBindTexture (gl_target, textures[i]));
|
_cogl_bind_gl_texture_transient (gl_target,
|
||||||
|
textures[i],
|
||||||
|
FALSE);
|
||||||
|
|
||||||
switch (gl_target)
|
switch (gl_target)
|
||||||
{
|
{
|
||||||
@ -123,6 +126,7 @@ _cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride,
|
|||||||
void
|
void
|
||||||
_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
||||||
GLuint gl_handle,
|
GLuint gl_handle,
|
||||||
|
gboolean is_foreign,
|
||||||
int src_x,
|
int src_x,
|
||||||
int src_y,
|
int src_y,
|
||||||
int dst_x,
|
int dst_x,
|
||||||
@ -141,7 +145,7 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
|||||||
src_y,
|
src_y,
|
||||||
bpp);
|
bpp);
|
||||||
|
|
||||||
GE( glBindTexture (gl_target, gl_handle) );
|
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||||
|
|
||||||
GE( glTexSubImage2D (gl_target, 0,
|
GE( glTexSubImage2D (gl_target, 0,
|
||||||
dst_x, dst_y,
|
dst_x, dst_y,
|
||||||
@ -154,6 +158,7 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
|||||||
void
|
void
|
||||||
_cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
_cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
||||||
GLuint gl_handle,
|
GLuint gl_handle,
|
||||||
|
gboolean is_foreign,
|
||||||
CoglBitmap *source_bmp,
|
CoglBitmap *source_bmp,
|
||||||
GLint internal_gl_format,
|
GLint internal_gl_format,
|
||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
@ -164,7 +169,7 @@ _cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
|||||||
/* Setup gl alignment to match rowstride and top-left corner */
|
/* Setup gl alignment to match rowstride and top-left corner */
|
||||||
prep_gl_for_pixels_upload_full (source_bmp->rowstride, 0, 0, bpp);
|
prep_gl_for_pixels_upload_full (source_bmp->rowstride, 0, 0, bpp);
|
||||||
|
|
||||||
GE( glBindTexture (gl_target, gl_handle) );
|
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||||
|
|
||||||
GE( glTexImage2D (gl_target, 0,
|
GE( glTexImage2D (gl_target, 0,
|
||||||
internal_gl_format,
|
internal_gl_format,
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "cogl-bitmap-private.h"
|
#include "cogl-bitmap-private.h"
|
||||||
#include "cogl-texture-private.h"
|
#include "cogl-texture-private.h"
|
||||||
#include "cogl-material.h"
|
#include "cogl-material.h"
|
||||||
|
#include "cogl-material-private.h"
|
||||||
#include "cogl-context.h"
|
#include "cogl-context.h"
|
||||||
#include "cogl-handle.h"
|
#include "cogl-handle.h"
|
||||||
#include "cogl-primitives.h"
|
#include "cogl-primitives.h"
|
||||||
@ -58,7 +59,7 @@ _cogl_texture_driver_gen (GLenum gl_target,
|
|||||||
|
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
GE (glBindTexture (gl_target, textures[i]));
|
_cogl_bind_gl_texture_transient (gl_target, textures[i], FALSE);
|
||||||
|
|
||||||
switch (gl_target)
|
switch (gl_target)
|
||||||
{
|
{
|
||||||
@ -91,6 +92,7 @@ _cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride,
|
|||||||
void
|
void
|
||||||
_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
||||||
GLuint gl_handle,
|
GLuint gl_handle,
|
||||||
|
gboolean is_foreign,
|
||||||
int src_x,
|
int src_x,
|
||||||
int src_y,
|
int src_y,
|
||||||
int dst_x,
|
int dst_x,
|
||||||
@ -131,7 +133,7 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
|||||||
slice_bmp.width,
|
slice_bmp.width,
|
||||||
slice_bmp.height);
|
slice_bmp.height);
|
||||||
|
|
||||||
GE( glBindTexture (gl_target, gl_handle) );
|
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||||
|
|
||||||
GE( glTexSubImage2D (gl_target, 0,
|
GE( glTexSubImage2D (gl_target, 0,
|
||||||
dst_x, dst_y,
|
dst_x, dst_y,
|
||||||
@ -147,6 +149,7 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
|||||||
void
|
void
|
||||||
_cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
_cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
||||||
GLuint gl_handle,
|
GLuint gl_handle,
|
||||||
|
gboolean is_foreign,
|
||||||
CoglBitmap *source_bmp,
|
CoglBitmap *source_bmp,
|
||||||
GLint internal_gl_format,
|
GLint internal_gl_format,
|
||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
@ -175,7 +178,7 @@ _cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
|||||||
_cogl_texture_driver_prep_gl_for_pixels_upload (bmp.rowstride,
|
_cogl_texture_driver_prep_gl_for_pixels_upload (bmp.rowstride,
|
||||||
bpp);
|
bpp);
|
||||||
|
|
||||||
GE( glBindTexture (gl_target, gl_handle) );
|
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||||
|
|
||||||
GE( glTexImage2D (gl_target, 0,
|
GE( glTexImage2D (gl_target, 0,
|
||||||
internal_gl_format,
|
internal_gl_format,
|
||||||
|
Loading…
Reference in New Issue
Block a user