mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 11:32:04 +00:00
Add a Cogl texture 3D backend
This adds a publicly exposed experimental API for a 3D texture backend. There is a feature flag which can be checked for whether 3D textures are supported. Although we require OpenGL 1.2 which has 3D textures in core, GLES only provides them through an extension so the feature can be used to detect that. The textures can be created with one of two new API functions :- cogl_texture_3d_new_with_size and cogl_texture_3d_new_from_data There is also internally a new_from_bitmap function. new_from_data is implemented in terms of this function. The two constructors are effectively the only way to upload data to a 3D texture. It does not work to call glTexImage2D with the GL_TEXTURE_3D target so the virtual for cogl_texture_set_region does nothing. It would be possible to make cogl_texture_get_data do something sensible like returning all of the images as a single long image but this is not currently implemented and instead the virtual just always fails. We may want to add API specific to the 3D texture backend to get and set a sub region of the texture. All of those three functions can throw a GError. This will happen if the GPU does not support 3D textures or it does not support NPOTs and an NPOT size is requested. It will also fail if the FBO extension is not supported and the COGL_TEXTURE_NO_AUTO_MIPMAP flag is not given. This could be avoided by copying the code for the GL_GENERATE_MIPMAP TexParameter fallback, but in the interests of keeping the code simple this is not yet done. This adds a couple of functions to cogl-texture-driver for uploading 3D data and querying the 3D proxy texture. prep_gl_for_pixels_upload_full now also takes sets the GL_UNPACK_IMAGE_HEIGHT parameter so that 3D textures can have padding between the images. Whenever 3D texture is uploading, both the height of the images and the height of all of the data is specified (either explicitly or implicilty from the CoglBitmap) so that the image height can be deduced by dividing by the depth.
This commit is contained in:
parent
159c7ed7e5
commit
5288f6d88d
@ -68,6 +68,7 @@ cogl_public_h = \
|
||||
$(srcdir)/cogl-pixel-array.h \
|
||||
$(srcdir)/cogl-shader.h \
|
||||
$(srcdir)/cogl-texture.h \
|
||||
$(srcdir)/cogl-texture-3d.h \
|
||||
$(srcdir)/cogl-types.h \
|
||||
$(srcdir)/cogl-vertex-buffer.h \
|
||||
$(srcdir)/cogl.h \
|
||||
@ -132,11 +133,13 @@ cogl_sources_c = \
|
||||
$(srcdir)/cogl-texture-private.h \
|
||||
$(srcdir)/cogl-texture-2d-private.h \
|
||||
$(srcdir)/cogl-texture-2d-sliced-private.h \
|
||||
$(srcdir)/cogl-texture-3d-private.h \
|
||||
$(srcdir)/cogl-texture-driver.h \
|
||||
$(srcdir)/cogl-sub-texture.c \
|
||||
$(srcdir)/cogl-texture.c \
|
||||
$(srcdir)/cogl-texture-2d.c \
|
||||
$(srcdir)/cogl-texture-2d-sliced.c \
|
||||
$(srcdir)/cogl-texture-3d.c \
|
||||
$(srcdir)/cogl-texture-rectangle-private.h \
|
||||
$(srcdir)/cogl-texture-rectangle.c \
|
||||
$(srcdir)/cogl-atlas.h \
|
||||
|
@ -68,6 +68,11 @@
|
||||
#define glUseProgram ctx->drv.pf_glUseProgram
|
||||
#endif
|
||||
|
||||
/* This might not be defined on GLES */
|
||||
#ifndef GL_TEXTURE_3D
|
||||
#define GL_TEXTURE_3D 0x806F
|
||||
#endif
|
||||
|
||||
typedef struct _CoglMaterialBackendARBfpPrivate
|
||||
{
|
||||
CoglMaterial *authority_cache;
|
||||
@ -415,6 +420,8 @@ gl_target_to_arbfp_string (GLenum gl_target)
|
||||
else if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
return "RECT";
|
||||
#endif
|
||||
else if (gl_target == GL_TEXTURE_3D)
|
||||
return "3D";
|
||||
else
|
||||
return "2D";
|
||||
}
|
||||
|
96
cogl/cogl-texture-3d-private.h
Normal file
96
cogl/cogl-texture-3d-private.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* This library 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 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Neil Roberts <neil@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifndef __COGL_TEXTURE_3D_PRIVATE_H
|
||||
#define __COGL_TEXTURE_3D_PRIVATE_H
|
||||
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-material-private.h"
|
||||
#include "cogl-texture-private.h"
|
||||
|
||||
#define COGL_TEXTURE_3D(tex) ((CoglTexture3D *) tex)
|
||||
|
||||
typedef struct _CoglTexture3D CoglTexture3D;
|
||||
|
||||
struct _CoglTexture3D
|
||||
{
|
||||
CoglTexture _parent;
|
||||
|
||||
/* The internal format of the GL texture represented as a
|
||||
CoglPixelFormat */
|
||||
CoglPixelFormat format;
|
||||
/* The internal format of the GL texture represented as a GL enum */
|
||||
GLenum gl_format;
|
||||
/* The texture object number */
|
||||
GLuint gl_texture;
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
GLenum min_filter;
|
||||
GLenum mag_filter;
|
||||
GLint wrap_mode_s;
|
||||
GLint wrap_mode_t;
|
||||
GLint wrap_mode_r;
|
||||
gboolean auto_mipmap;
|
||||
gboolean mipmaps_dirty;
|
||||
};
|
||||
|
||||
GQuark
|
||||
_cogl_handle_texture_3d_get_type (void);
|
||||
|
||||
/*
|
||||
* cogl_texture_3d_new_from_bitmap:
|
||||
* @bmp_handle: A #CoglHandle to a bitmap.
|
||||
* @height: height of the texture in pixels.
|
||||
* @depth: depth of the texture in pixels.
|
||||
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
|
||||
* @internal_format: the #CoglPixelFormat that will be used for storing
|
||||
* the buffer on the GPU. If COGL_PIXEL_FORMAT_ANY is given then a
|
||||
* premultiplied format similar to the format of the source data will
|
||||
* be used. The default blending equations of Cogl expect premultiplied
|
||||
* color data; the main use of passing a non-premultiplied format here
|
||||
* is if you have non-premultiplied source data and are going to adjust
|
||||
* the blend mode (see cogl_material_set_blend()) or use the data for
|
||||
* something other than straight blending.
|
||||
* @error: A GError return location.
|
||||
*
|
||||
* Creates a new 3D texture and initializes it with the images in
|
||||
* @bmp_handle. The images are assumed to be packed together after one
|
||||
* another in the increasing y axis. The height of individual image is
|
||||
* given as @height and the number of images is given in @depth. The
|
||||
* actual height of the bitmap can be larger than @height × @depth. In
|
||||
* this case it assumes there is padding between the images.
|
||||
*
|
||||
* Return value: the newly created texture or %COGL_INVALID_HANDLE if
|
||||
* there was an error.
|
||||
*/
|
||||
CoglHandle
|
||||
_cogl_texture_3d_new_from_bitmap (CoglHandle bmp_handle,
|
||||
unsigned int height,
|
||||
unsigned int depth,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format,
|
||||
GError **error);
|
||||
|
||||
#endif /* __COGL_TEXTURE_3D_PRIVATE_H */
|
657
cogl/cogl-texture-3d.c
Normal file
657
cogl/cogl-texture-3d.c
Normal file
@ -0,0 +1,657 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* This library 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 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Neil Roberts <neil@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "cogl.h"
|
||||
#include "cogl-internal.h"
|
||||
#include "cogl-util.h"
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-texture-2d-private.h"
|
||||
#include "cogl-texture-3d-private.h"
|
||||
#include "cogl-texture-driver.h"
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-journal-private.h"
|
||||
#include "cogl-material-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/* These might not be defined on GLES */
|
||||
#ifndef GL_TEXTURE_3D
|
||||
#define GL_TEXTURE_3D 0x806F
|
||||
#endif
|
||||
#ifndef GL_TEXTURE_WRAP_R
|
||||
#define GL_TEXTURE_WRAP_R 0x8072
|
||||
#endif
|
||||
|
||||
#define glTexImage3D ctx->drv.pf_glTexImage3D
|
||||
|
||||
static void _cogl_texture_3d_free (CoglTexture3D *tex_3d);
|
||||
|
||||
COGL_TEXTURE_DEFINE (Texture3D, texture_3d);
|
||||
|
||||
static const CoglTextureVtable cogl_texture_3d_vtable;
|
||||
|
||||
typedef struct _CoglTexture3DManualRepeatData
|
||||
{
|
||||
CoglTexture3D *tex_3d;
|
||||
CoglTextureSliceCallback callback;
|
||||
void *user_data;
|
||||
} CoglTexture3DManualRepeatData;
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_wrap_coords (float t_1, float t_2,
|
||||
float *out_t_1, float *out_t_2)
|
||||
{
|
||||
float int_part;
|
||||
|
||||
/* Wrap t_1 and t_2 to the range [0,1] */
|
||||
|
||||
modff (t_1 < t_2 ? t_1 : t_2, &int_part);
|
||||
t_1 -= int_part;
|
||||
t_2 -= int_part;
|
||||
if (cogl_util_float_signbit (int_part))
|
||||
{
|
||||
*out_t_1 = 1.0f + t_1;
|
||||
*out_t_2 = 1.0f + t_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out_t_1 = t_1;
|
||||
*out_t_2 = t_2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_manual_repeat_cb (const float *coords,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTexture3DManualRepeatData *data = user_data;
|
||||
float slice_coords[4];
|
||||
|
||||
_cogl_texture_3d_wrap_coords (coords[0], coords[2],
|
||||
slice_coords + 0, slice_coords + 2);
|
||||
_cogl_texture_3d_wrap_coords (coords[1], coords[3],
|
||||
slice_coords + 1, slice_coords + 3);
|
||||
|
||||
data->callback (COGL_TEXTURE (data->tex_3d),
|
||||
data->tex_3d->gl_texture,
|
||||
GL_TEXTURE_3D,
|
||||
slice_coords,
|
||||
coords,
|
||||
data->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_foreach_sub_texture_in_region (
|
||||
CoglTexture *tex,
|
||||
float virtual_tx_1,
|
||||
float virtual_ty_1,
|
||||
float virtual_tx_2,
|
||||
float virtual_ty_2,
|
||||
CoglTextureSliceCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
|
||||
CoglTexture3DManualRepeatData data;
|
||||
|
||||
data.tex_3d = tex_3d;
|
||||
data.callback = callback;
|
||||
data.user_data = user_data;
|
||||
|
||||
/* We need to implement manual repeating because if Cogl is calling
|
||||
this function then it will set the wrap mode to GL_CLAMP_TO_EDGE
|
||||
and hardware repeating can't be done */
|
||||
_cogl_texture_iterate_manual_repeats (_cogl_texture_3d_manual_repeat_cb,
|
||||
virtual_tx_1, virtual_ty_1,
|
||||
virtual_tx_2, virtual_ty_2,
|
||||
&data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_set_wrap_mode_parameters (CoglTexture *tex,
|
||||
GLenum wrap_mode_s,
|
||||
GLenum wrap_mode_t,
|
||||
GLenum wrap_mode_r)
|
||||
{
|
||||
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
|
||||
|
||||
/* Only set the wrap mode if it's different from the current value
|
||||
to avoid too many GL calls. */
|
||||
if (tex_3d->wrap_mode_s != wrap_mode_s ||
|
||||
tex_3d->wrap_mode_t != wrap_mode_t ||
|
||||
tex_3d->wrap_mode_r != wrap_mode_r)
|
||||
{
|
||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
|
||||
tex_3d->gl_texture,
|
||||
FALSE);
|
||||
GE( glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrap_mode_s) );
|
||||
GE( glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrap_mode_t) );
|
||||
GE( glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrap_mode_r) );
|
||||
|
||||
tex_3d->wrap_mode_s = wrap_mode_s;
|
||||
tex_3d->wrap_mode_t = wrap_mode_t;
|
||||
tex_3d->wrap_mode_r = wrap_mode_r;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_free (CoglTexture3D *tex_3d)
|
||||
{
|
||||
_cogl_delete_gl_texture (tex_3d->gl_texture);
|
||||
|
||||
/* Chain up */
|
||||
_cogl_texture_free (COGL_TEXTURE (tex_3d));
|
||||
}
|
||||
|
||||
static CoglTexture3D *
|
||||
_cogl_texture_3d_create_base (unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int depth,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
CoglTexture3D *tex_3d = g_new (CoglTexture3D, 1);
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_3d);
|
||||
|
||||
tex->vtable = &cogl_texture_3d_vtable;
|
||||
|
||||
tex_3d->width = width;
|
||||
tex_3d->height = height;
|
||||
tex_3d->depth = depth;
|
||||
tex_3d->mipmaps_dirty = TRUE;
|
||||
tex_3d->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
||||
|
||||
/* We default to GL_LINEAR for both filters */
|
||||
tex_3d->min_filter = GL_LINEAR;
|
||||
tex_3d->mag_filter = GL_LINEAR;
|
||||
|
||||
/* Wrap mode not yet set */
|
||||
tex_3d->wrap_mode_s = GL_FALSE;
|
||||
tex_3d->wrap_mode_t = GL_FALSE;
|
||||
tex_3d->wrap_mode_r = GL_FALSE;
|
||||
|
||||
tex_3d->format = internal_format;
|
||||
|
||||
return tex_3d;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_3d_can_create (unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int depth,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format,
|
||||
GError **error)
|
||||
{
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_type;
|
||||
|
||||
/* This should only happen on GLES */
|
||||
if (!cogl_features_available (COGL_FEATURE_TEXTURE_3D))
|
||||
{
|
||||
g_set_error (error,
|
||||
COGL_ERROR,
|
||||
COGL_ERROR_UNSUPPORTED,
|
||||
"3D textures are not supported by the GPU");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If the driver doesn't support glGenerateMipmap then we need to
|
||||
store a copy of the first pixels to cause an update. Instead of
|
||||
duplicating the code here we'll just make it throw an error */
|
||||
if ((flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0 &&
|
||||
!cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||
{
|
||||
g_set_error (error,
|
||||
COGL_ERROR,
|
||||
COGL_ERROR_UNSUPPORTED,
|
||||
"Auto mipmapping was requested but this is not supported "
|
||||
"by Cogl with this driver");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If NPOT textures aren't supported then the size must be a power
|
||||
of two */
|
||||
if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
|
||||
(!_cogl_util_is_pot (width) ||
|
||||
!_cogl_util_is_pot (height) ||
|
||||
!_cogl_util_is_pot (depth)))
|
||||
{
|
||||
g_set_error (error,
|
||||
COGL_ERROR,
|
||||
COGL_ERROR_UNSUPPORTED,
|
||||
"A non-power-of-two size was requested but this is not "
|
||||
"supported by the GPU");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_cogl_pixel_format_to_gl (internal_format,
|
||||
&gl_intformat,
|
||||
NULL,
|
||||
&gl_type);
|
||||
|
||||
/* Check that the driver can create a texture with that size */
|
||||
if (!_cogl_texture_driver_size_supported_3d (GL_TEXTURE_3D,
|
||||
gl_intformat,
|
||||
gl_type,
|
||||
width,
|
||||
height,
|
||||
depth))
|
||||
{
|
||||
g_set_error (error,
|
||||
COGL_ERROR,
|
||||
COGL_ERROR_UNSUPPORTED,
|
||||
"The requested dimensions are not supported by the GPU");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_texture_3d_new_with_size (unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int depth,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture3D *tex_3d;
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||
|
||||
/* Since no data, we need some internal format */
|
||||
if (internal_format == COGL_PIXEL_FORMAT_ANY)
|
||||
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||
|
||||
if (!_cogl_texture_3d_can_create (width, height, depth,
|
||||
flags, internal_format,
|
||||
error))
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
internal_format = _cogl_pixel_format_to_gl (internal_format,
|
||||
&gl_intformat,
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
tex_3d = _cogl_texture_3d_create_base (width, height, depth,
|
||||
flags, internal_format);
|
||||
|
||||
_cogl_texture_driver_gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture);
|
||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
|
||||
tex_3d->gl_texture,
|
||||
FALSE);
|
||||
GE( glTexImage3D (GL_TEXTURE_3D, 0, gl_intformat,
|
||||
width, height, depth, 0, gl_format, gl_type, NULL) );
|
||||
|
||||
return _cogl_texture_3d_handle_new (tex_3d);
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_3d_new_from_bitmap (CoglHandle bmp_handle,
|
||||
unsigned int height,
|
||||
unsigned int depth,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture3D *tex_3d;
|
||||
CoglBitmap *bmp = (CoglBitmap *) bmp_handle;
|
||||
CoglBitmap dst_bmp;
|
||||
gboolean dst_bmp_owner;
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||
|
||||
internal_format = _cogl_texture_determine_internal_format (bmp->format,
|
||||
internal_format);
|
||||
|
||||
if (!_cogl_texture_3d_can_create (bmp->width, height, depth,
|
||||
flags, internal_format,
|
||||
error))
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
if (!_cogl_texture_prepare_for_upload (bmp,
|
||||
internal_format,
|
||||
&internal_format,
|
||||
&dst_bmp,
|
||||
&dst_bmp_owner,
|
||||
&gl_intformat,
|
||||
&gl_format,
|
||||
&gl_type))
|
||||
{
|
||||
g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_FAILED,
|
||||
"Bitmap conversion failed");
|
||||
return COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
tex_3d = _cogl_texture_3d_create_base (dst_bmp.width, height, depth,
|
||||
flags, internal_format);
|
||||
|
||||
_cogl_texture_driver_gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture);
|
||||
|
||||
_cogl_texture_driver_upload_to_gl_3d (GL_TEXTURE_3D,
|
||||
tex_3d->gl_texture,
|
||||
FALSE, /* is_foreign */
|
||||
height,
|
||||
depth,
|
||||
&dst_bmp,
|
||||
gl_intformat,
|
||||
gl_format,
|
||||
gl_type);
|
||||
|
||||
tex_3d->gl_format = gl_intformat;
|
||||
|
||||
if (dst_bmp_owner)
|
||||
g_free (dst_bmp.data);
|
||||
|
||||
return _cogl_texture_3d_handle_new (tex_3d);
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_texture_3d_new_from_data (unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int depth,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat format,
|
||||
CoglPixelFormat internal_format,
|
||||
unsigned int rowstride,
|
||||
unsigned int image_stride,
|
||||
const guint8 *data,
|
||||
GError **error)
|
||||
{
|
||||
CoglBitmap bitmap;
|
||||
gboolean bitmap_owned = FALSE;
|
||||
CoglHandle ret;
|
||||
|
||||
/* These are considered a programmer errors so we won't set a
|
||||
GError. It would be nice if this was a g_return_if_fail but the
|
||||
rest of Cogl isn't using that */
|
||||
if (format == COGL_PIXEL_FORMAT_ANY)
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
if (data == NULL)
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
/* Rowstride from width if not given */
|
||||
if (rowstride == 0)
|
||||
rowstride = width * _cogl_get_format_bpp (format);
|
||||
/* Image stride from height and rowstride if not given */
|
||||
if (image_stride == 0)
|
||||
image_stride = height * rowstride;
|
||||
|
||||
if (image_stride < rowstride * height)
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
/* GL doesn't support uploading when the image_stride isn't a
|
||||
multiple of the rowstride. If this happens we'll just pack the
|
||||
image into a new bitmap. The documentation for this function
|
||||
recommends avoiding this situation. */
|
||||
if (image_stride % rowstride != 0)
|
||||
{
|
||||
int z, y;
|
||||
|
||||
bitmap.width = width;
|
||||
bitmap.height = depth * height;
|
||||
bitmap.rowstride = _cogl_get_format_bpp (format) * width;
|
||||
bitmap.data = g_malloc (bitmap.rowstride * height * depth);
|
||||
bitmap.format = format;
|
||||
|
||||
/* Copy all of the images in */
|
||||
for (z = 0; z < depth; z++)
|
||||
for (y = 0; y < height; y++)
|
||||
memcpy (bitmap.data + (z * bitmap.rowstride * height +
|
||||
bitmap.rowstride * y),
|
||||
data + z * image_stride + rowstride * y,
|
||||
bitmap.rowstride);
|
||||
|
||||
bitmap_owned = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wrap the data into a bitmap */
|
||||
bitmap.width = width;
|
||||
bitmap.height = image_stride / rowstride * depth;
|
||||
bitmap.data = (guint8 *) data;
|
||||
bitmap.format = format;
|
||||
bitmap.rowstride = rowstride;
|
||||
}
|
||||
|
||||
ret = _cogl_texture_3d_new_from_bitmap (&bitmap,
|
||||
height,
|
||||
depth,
|
||||
flags,
|
||||
internal_format,
|
||||
error);
|
||||
|
||||
if (bitmap_owned)
|
||||
g_free (bitmap.data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GQuark
|
||||
cogl_texture_3d_error_quark (void)
|
||||
{
|
||||
return g_quark_from_static_string ("cogl-texture-3d-error-quark");
|
||||
}
|
||||
|
||||
static int
|
||||
_cogl_texture_3d_get_max_waste (CoglTexture *tex)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_3d_is_sliced (CoglTexture *tex)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_3d_can_hardware_repeat (CoglTexture *tex)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_transform_coords_to_gl (CoglTexture *tex,
|
||||
float *s,
|
||||
float *t)
|
||||
{
|
||||
/* The texture coordinates map directly so we don't need to do
|
||||
anything */
|
||||
}
|
||||
|
||||
static CoglTransformResult
|
||||
_cogl_texture_3d_transform_quad_coords_to_gl (CoglTexture *tex,
|
||||
float *coords)
|
||||
{
|
||||
/* The texture coordinates map directly so we don't need to do
|
||||
anything other than check for repeats */
|
||||
|
||||
gboolean need_repeat = FALSE;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
if (coords[i] < 0.0f || coords[i] > 1.0f)
|
||||
need_repeat = TRUE;
|
||||
|
||||
return (need_repeat ? COGL_TRANSFORM_HARDWARE_REPEAT
|
||||
: COGL_TRANSFORM_NO_REPEAT);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_3d_get_gl_texture (CoglTexture *tex,
|
||||
GLuint *out_gl_handle,
|
||||
GLenum *out_gl_target)
|
||||
{
|
||||
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
|
||||
|
||||
if (out_gl_handle)
|
||||
*out_gl_handle = tex_3d->gl_texture;
|
||||
|
||||
if (out_gl_target)
|
||||
*out_gl_target = GL_TEXTURE_3D;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_set_filters (CoglTexture *tex,
|
||||
GLenum min_filter,
|
||||
GLenum mag_filter)
|
||||
{
|
||||
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
|
||||
|
||||
if (min_filter == tex_3d->min_filter
|
||||
&& mag_filter == tex_3d->mag_filter)
|
||||
return;
|
||||
|
||||
/* Store new values */
|
||||
tex_3d->min_filter = min_filter;
|
||||
tex_3d->mag_filter = mag_filter;
|
||||
|
||||
/* Apply new filters to the texture */
|
||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
|
||||
tex_3d->gl_texture,
|
||||
FALSE);
|
||||
GE( glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, mag_filter) );
|
||||
GE( glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, min_filter) );
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
|
||||
{
|
||||
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Only update if the mipmaps are dirty */
|
||||
if ((flags & COGL_TEXTURE_NEEDS_MIPMAP) &&
|
||||
tex_3d->auto_mipmap && tex_3d->mipmaps_dirty)
|
||||
{
|
||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
|
||||
tex_3d->gl_texture,
|
||||
FALSE);
|
||||
/* glGenerateMipmap is defined in the FBO extension. We only allow
|
||||
CoglTexture3D instances to be created if this feature is
|
||||
available so we don't need to check for the extension */
|
||||
_cogl_texture_driver_gl_generate_mipmaps (GL_TEXTURE_3D);
|
||||
|
||||
tex_3d->mipmaps_dirty = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_ensure_non_quad_rendering (CoglTexture *tex)
|
||||
{
|
||||
/* Nothing needs to be done */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_3d_set_region (CoglTexture *tex,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int dst_width,
|
||||
unsigned int dst_height,
|
||||
CoglBitmap *bmp)
|
||||
{
|
||||
/* This function doesn't really make sense for 3D textures because
|
||||
it can't specify which image to upload to */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
_cogl_texture_3d_get_data (CoglTexture *tex,
|
||||
CoglPixelFormat format,
|
||||
unsigned int rowstride,
|
||||
guint8 *data)
|
||||
{
|
||||
/* FIXME: we could probably implement this by assuming the data is
|
||||
big enough to hold all of the images and that there is no stride
|
||||
between the images. However it would be better to have an API
|
||||
that can provide an image stride and this function probably isn't
|
||||
particularly useful anyway so for now it just reports failure */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CoglPixelFormat
|
||||
_cogl_texture_3d_get_format (CoglTexture *tex)
|
||||
{
|
||||
return COGL_TEXTURE_3D (tex)->format;
|
||||
}
|
||||
|
||||
static GLenum
|
||||
_cogl_texture_3d_get_gl_format (CoglTexture *tex)
|
||||
{
|
||||
return COGL_TEXTURE_3D (tex)->gl_format;
|
||||
}
|
||||
|
||||
static int
|
||||
_cogl_texture_3d_get_width (CoglTexture *tex)
|
||||
{
|
||||
return COGL_TEXTURE_3D (tex)->width;
|
||||
}
|
||||
|
||||
static int
|
||||
_cogl_texture_3d_get_height (CoglTexture *tex)
|
||||
{
|
||||
return COGL_TEXTURE_3D (tex)->height;
|
||||
}
|
||||
|
||||
static const CoglTextureVtable
|
||||
cogl_texture_3d_vtable =
|
||||
{
|
||||
_cogl_texture_3d_set_region,
|
||||
_cogl_texture_3d_get_data,
|
||||
_cogl_texture_3d_foreach_sub_texture_in_region,
|
||||
_cogl_texture_3d_get_max_waste,
|
||||
_cogl_texture_3d_is_sliced,
|
||||
_cogl_texture_3d_can_hardware_repeat,
|
||||
_cogl_texture_3d_transform_coords_to_gl,
|
||||
_cogl_texture_3d_transform_quad_coords_to_gl,
|
||||
_cogl_texture_3d_get_gl_texture,
|
||||
_cogl_texture_3d_set_filters,
|
||||
_cogl_texture_3d_pre_paint,
|
||||
_cogl_texture_3d_ensure_non_quad_rendering,
|
||||
_cogl_texture_3d_set_wrap_mode_parameters,
|
||||
_cogl_texture_3d_get_format,
|
||||
_cogl_texture_3d_get_gl_format,
|
||||
_cogl_texture_3d_get_width,
|
||||
_cogl_texture_3d_get_height,
|
||||
NULL /* is_foreign */
|
||||
};
|
154
cogl/cogl-texture-3d.h
Normal file
154
cogl/cogl-texture-3d.h
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* This library 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 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Authors:
|
||||
* Neil Roberts <neil@linux.intel.com>
|
||||
*/
|
||||
|
||||
#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cogl/cogl.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __COGL_TEXTURE_3D_H
|
||||
#define __COGL_TEXTURE_3D_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:cogl-texture-3d
|
||||
* @short_description: Fuctions for creating and manipulating 3D textures
|
||||
*
|
||||
* These functions allow 3D textures to be used. 3D textures can be
|
||||
* thought of as layers of 2D images arranged into a cuboid
|
||||
* shape. When choosing a texel from the texture, Cogl will take into
|
||||
* account the 'r' texture coordinate to select one of the images.
|
||||
*/
|
||||
|
||||
/* All of the cogl-texture-3d API is currently experimental so we
|
||||
* suffix the actual symbols with _EXP so if somone is monitoring for
|
||||
* ABI changes it will hopefully be clearer to them what's going on if
|
||||
* any of the symbols dissapear at a later date.
|
||||
*/
|
||||
#define cogl_texture_3d_new_with_size cogl_texture_3d_new_with_size_EXP
|
||||
#define cogl_texture_3d_new_from_data cogl_texture_3d_new_from_data_EXP
|
||||
#define cogl_is_texture_3d cogl_is_texture_3d_EXP
|
||||
|
||||
/**
|
||||
* cogl_texture_3d_new_with_size:
|
||||
* @width: width of the texture in pixels.
|
||||
* @height: height of the texture in pixels.
|
||||
* @depth: depth of the texture in pixels.
|
||||
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
|
||||
* @internal_format: the #CoglPixelFormat to use for the GPU
|
||||
* storage of the texture.
|
||||
* @error: A GError return location.
|
||||
*
|
||||
* Creates a new Cogl 3D texture with the specified dimensions and
|
||||
* pixel format.
|
||||
*
|
||||
* Note that this function will throw a #GError if
|
||||
* %COGL_FEATURE_TEXTURE_3D is not advertised. It can also fail if the
|
||||
* requested dimensions are not supported by the GPU.
|
||||
*
|
||||
* Return value: a new handle to a CoglTexture3D object or
|
||||
* %COGL_INVALID_HANDLE on failure.
|
||||
* Since: 1.4
|
||||
* Stability: Unstable
|
||||
*/
|
||||
CoglHandle
|
||||
cogl_texture_3d_new_with_size (unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int depth,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* cogl_texture_3d_new_from_data:
|
||||
* @width: width of the texture in pixels.
|
||||
* @height: height of the texture in pixels.
|
||||
* @depth: depth of the texture in pixels.
|
||||
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
|
||||
* @format: the #CoglPixelFormat the buffer is stored in in RAM
|
||||
* @internal_format: the #CoglPixelFormat that will be used for storing
|
||||
* the buffer on the GPU. If COGL_PIXEL_FORMAT_ANY is given then a
|
||||
* premultiplied format similar to the format of the source data will
|
||||
* be used. The default blending equations of Cogl expect premultiplied
|
||||
* color data; the main use of passing a non-premultiplied format here
|
||||
* is if you have non-premultiplied source data and are going to adjust
|
||||
* the blend mode (see cogl_material_set_blend()) or use the data for
|
||||
* something other than straight blending.
|
||||
* @rowstride: the memory offset in bytes between the starts of
|
||||
* scanlines in @data or 0 to infer it from the width and format
|
||||
* @image_stride: the number of bytes from one image to the next. This
|
||||
* can be used to add padding between the images in a similar way
|
||||
* that the rowstride can be used to add padding between
|
||||
* rows. Alternatively 0 can be passed to infer the @image_stride
|
||||
* from the @height.
|
||||
* @data: pointer the memory region where the source buffer resides
|
||||
* @error: A GError return location.
|
||||
*
|
||||
* Creates a new 3D texture and initializes it with @data. The data is
|
||||
* assumed to be packed array of @depth images. There can be padding
|
||||
* between the images using @image_stride.
|
||||
*
|
||||
* Note that this function will throw a #GError if
|
||||
* %COGL_FEATURE_TEXTURE_3D is not advertised. It can also fail if the
|
||||
* requested dimensions are not supported by the GPU.
|
||||
*
|
||||
* Return value: the newly created texture or %COGL_INVALID_HANDLE if
|
||||
* there was an error.
|
||||
* Since: 1.4
|
||||
* Stability: Unstable
|
||||
*/
|
||||
CoglHandle
|
||||
cogl_texture_3d_new_from_data (unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int depth,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat format,
|
||||
CoglPixelFormat internal_format,
|
||||
unsigned int rowstride,
|
||||
unsigned int image_stride,
|
||||
const guint8 *data,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* cogl_is_texture_3d:
|
||||
* @handle: a #CoglHandle
|
||||
*
|
||||
* Checks whether @handle is a #CoglHandle for a 3D texture.
|
||||
*
|
||||
* Return value: %TRUE if the passed handle represents a 3D texture
|
||||
* and %FALSE otherwise
|
||||
*
|
||||
* Since: 1.4
|
||||
* Stability: Unstable
|
||||
*/
|
||||
gboolean
|
||||
cogl_is_texture_3d (CoglHandle handle);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COGL_TEXTURE_3D_H */
|
@ -87,6 +87,24 @@ _cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
||||
GLuint source_gl_format,
|
||||
GLuint source_gl_type);
|
||||
|
||||
/*
|
||||
* Replaces the contents of the GL texture with the entire bitmap. The
|
||||
* width of the texture is inferred from the bitmap. The height and
|
||||
* depth of the texture is given directly. The 'image_height' (which
|
||||
* is the number of rows between images) is inferred by dividing the
|
||||
* height of the bitmap by the depth.
|
||||
*/
|
||||
void
|
||||
_cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
|
||||
GLuint gl_handle,
|
||||
gboolean is_foreign,
|
||||
GLint height,
|
||||
GLint depth,
|
||||
CoglBitmap *source_bmp,
|
||||
GLint internal_gl_format,
|
||||
GLuint source_gl_format,
|
||||
GLuint source_gl_type);
|
||||
|
||||
/*
|
||||
* This sets up the glPixelStore state for an download to a destination with
|
||||
* the same size, and with no offset.
|
||||
@ -131,6 +149,14 @@ _cogl_texture_driver_size_supported (GLenum gl_target,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_size_supported_3d (GLenum gl_target,
|
||||
GLenum gl_format,
|
||||
GLenum gl_type,
|
||||
int width,
|
||||
int height,
|
||||
int depth);
|
||||
|
||||
/*
|
||||
* This driver abstraction is needed because GLES doesn't support setting
|
||||
* a texture border color.
|
||||
|
@ -250,6 +250,7 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
|
||||
* hardware.
|
||||
* @COGL_FEATURE_POINT_SPRITE: Whether
|
||||
* cogl_material_set_layer_point_sprite_coords_enabled() is supported.
|
||||
* @COGL_FEATURE_TEXTURE_3D: 3D texture support
|
||||
*
|
||||
* Flags for the supported features.
|
||||
*
|
||||
@ -274,7 +275,8 @@ typedef enum
|
||||
COGL_FEATURE_TEXTURE_NPOT_BASIC = (1 << 15),
|
||||
COGL_FEATURE_TEXTURE_NPOT_MIPMAP = (1 << 16),
|
||||
COGL_FEATURE_TEXTURE_NPOT_REPEAT = (1 << 17),
|
||||
COGL_FEATURE_POINT_SPRITE = (1 << 18)
|
||||
COGL_FEATURE_POINT_SPRITE = (1 << 18),
|
||||
COGL_FEATURE_TEXTURE_3D = (1 << 19)
|
||||
} CoglFeatureFlags;
|
||||
|
||||
/**
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include <cogl/cogl-buffer.h>
|
||||
#include <cogl/cogl-pixel-array.h>
|
||||
#include <cogl/cogl-vector.h>
|
||||
#include <cogl/cogl-texture-3d.h>
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
@ -344,6 +344,20 @@ COGL_FEATURE_FUNCTION (void, glBlendColor,
|
||||
GLclampf alpha))
|
||||
COGL_FEATURE_END ()
|
||||
|
||||
COGL_FEATURE_BEGIN (texture_3d, 1, 2,
|
||||
"\0",
|
||||
"\0",
|
||||
COGL_FEATURE_TEXTURE_3D,
|
||||
0)
|
||||
COGL_FEATURE_FUNCTION (void, glTexImage3D,
|
||||
(GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels))
|
||||
COGL_FEATURE_END ()
|
||||
|
||||
/* Available in GL 1.3 or the multitexture extension. These are
|
||||
required */
|
||||
COGL_FEATURE_BEGIN (multitexture, 1, 3,
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#define glGenerateMipmap ctx->drv.pf_glGenerateMipmap
|
||||
#define glTexImage3D ctx->drv.pf_glTexImage3D
|
||||
|
||||
void
|
||||
_cogl_texture_driver_gen (GLenum gl_target,
|
||||
@ -65,20 +66,22 @@ _cogl_texture_driver_gen (GLenum gl_target,
|
||||
|
||||
switch (gl_target)
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
/* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
|
||||
GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
|
||||
break;
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_TEXTURE_3D:
|
||||
/* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
|
||||
GE( glTexParameteri (gl_target,
|
||||
GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR) );
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_RECTANGLE_ARB:
|
||||
/* Texture rectangles already default to GL_LINEAR so nothing
|
||||
needs to be done */
|
||||
break;
|
||||
case GL_TEXTURE_RECTANGLE_ARB:
|
||||
/* Texture rectangles already default to GL_LINEAR so nothing
|
||||
needs to be done */
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,6 +89,7 @@ _cogl_texture_driver_gen (GLenum gl_target,
|
||||
* source buffer */
|
||||
static void
|
||||
prep_gl_for_pixels_upload_full (int pixels_rowstride,
|
||||
int image_height,
|
||||
int pixels_src_x,
|
||||
int pixels_src_y,
|
||||
int pixels_bpp)
|
||||
@ -95,6 +99,9 @@ prep_gl_for_pixels_upload_full (int pixels_rowstride,
|
||||
GE( glPixelStorei (GL_UNPACK_SKIP_PIXELS, pixels_src_x) );
|
||||
GE( glPixelStorei (GL_UNPACK_SKIP_ROWS, pixels_src_y) );
|
||||
|
||||
if (cogl_features_available (COGL_FEATURE_TEXTURE_3D))
|
||||
GE( glPixelStorei (GL_UNPACK_IMAGE_HEIGHT, image_height) );
|
||||
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_upload (pixels_rowstride);
|
||||
}
|
||||
|
||||
@ -102,13 +109,14 @@ void
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride,
|
||||
int pixels_bpp)
|
||||
{
|
||||
prep_gl_for_pixels_upload_full (pixels_rowstride, 0, 0, pixels_bpp);
|
||||
prep_gl_for_pixels_upload_full (pixels_rowstride, 0, 0, 0, pixels_bpp);
|
||||
}
|
||||
|
||||
/* OpenGL - unlike GLES - can download pixel data into a sub region of
|
||||
* a larger destination buffer */
|
||||
static void
|
||||
prep_gl_for_pixels_download_full (int pixels_rowstride,
|
||||
int image_height,
|
||||
int pixels_src_x,
|
||||
int pixels_src_y,
|
||||
int pixels_bpp)
|
||||
@ -118,6 +126,9 @@ prep_gl_for_pixels_download_full (int pixels_rowstride,
|
||||
GE( glPixelStorei (GL_PACK_SKIP_PIXELS, pixels_src_x) );
|
||||
GE( glPixelStorei (GL_PACK_SKIP_ROWS, pixels_src_y) );
|
||||
|
||||
if (cogl_features_available (COGL_FEATURE_TEXTURE_3D))
|
||||
GE( glPixelStorei (GL_PACK_IMAGE_HEIGHT, image_height) );
|
||||
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_download (pixels_rowstride);
|
||||
}
|
||||
|
||||
@ -125,7 +136,7 @@ void
|
||||
_cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride,
|
||||
int pixels_bpp)
|
||||
{
|
||||
prep_gl_for_pixels_download_full (pixels_rowstride, 0, 0, pixels_bpp);
|
||||
prep_gl_for_pixels_download_full (pixels_rowstride, 0, 0, 0, pixels_bpp);
|
||||
}
|
||||
|
||||
void
|
||||
@ -146,6 +157,7 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
||||
|
||||
/* Setup gl alignment to match rowstride and top-left corner */
|
||||
prep_gl_for_pixels_upload_full (source_bmp->rowstride,
|
||||
0,
|
||||
src_x,
|
||||
src_y,
|
||||
bpp);
|
||||
@ -172,7 +184,7 @@ _cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
||||
int bpp = _cogl_get_format_bpp (source_bmp->format);
|
||||
|
||||
/* 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, 0, bpp);
|
||||
|
||||
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||
|
||||
@ -185,6 +197,40 @@ _cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
||||
source_bmp->data) );
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
|
||||
GLuint gl_handle,
|
||||
gboolean is_foreign,
|
||||
GLint height,
|
||||
GLint depth,
|
||||
CoglBitmap *source_bmp,
|
||||
GLint internal_gl_format,
|
||||
GLuint source_gl_format,
|
||||
GLuint source_gl_type)
|
||||
{
|
||||
int bpp = _cogl_get_format_bpp (source_bmp->format);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Setup gl alignment to match rowstride and top-left corner */
|
||||
prep_gl_for_pixels_upload_full (source_bmp->rowstride,
|
||||
source_bmp->height / depth,
|
||||
0, 0, bpp);
|
||||
|
||||
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||
|
||||
GE( glTexImage3D (gl_target,
|
||||
0, /* level */
|
||||
internal_gl_format,
|
||||
source_bmp->width,
|
||||
height,
|
||||
depth,
|
||||
0,
|
||||
source_gl_format,
|
||||
source_gl_type,
|
||||
source_bmp->data) );
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_gl_get_tex_image (GLenum gl_target,
|
||||
GLenum dest_gl_format,
|
||||
@ -199,6 +245,36 @@ _cogl_texture_driver_gl_get_tex_image (GLenum gl_target,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_size_supported_3d (GLenum gl_target,
|
||||
GLenum gl_format,
|
||||
GLenum gl_type,
|
||||
int width,
|
||||
int height,
|
||||
int depth)
|
||||
{
|
||||
GLenum proxy_target;
|
||||
GLint new_width = 0;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
if (gl_target == GL_TEXTURE_3D)
|
||||
proxy_target = GL_PROXY_TEXTURE_3D;
|
||||
else
|
||||
/* Unknown target, assume it's not supported */
|
||||
return FALSE;
|
||||
|
||||
/* Proxy texture allows for a quick check for supported size */
|
||||
GE( glTexImage3D (proxy_target, 0, GL_RGBA,
|
||||
width, height, depth, 0 /* border */,
|
||||
gl_format, gl_type, NULL) );
|
||||
|
||||
GE( glGetTexLevelParameteriv (proxy_target, 0,
|
||||
GL_TEXTURE_WIDTH, &new_width) );
|
||||
|
||||
return new_width != 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_size_supported (GLenum gl_target,
|
||||
GLenum gl_format,
|
||||
|
@ -90,3 +90,22 @@ COGL_FEATURE_BEGIN (texture_npot, 255, 255,
|
||||
COGL_FEATURE_TEXTURE_NPOT_REPEAT,
|
||||
0)
|
||||
COGL_FEATURE_END ()
|
||||
|
||||
COGL_FEATURE_BEGIN (texture_3d, 1, 2,
|
||||
"OES\0",
|
||||
"texture_3D\0",
|
||||
COGL_FEATURE_TEXTURE_3D,
|
||||
0)
|
||||
COGL_FEATURE_FUNCTION (void, glTexImage3D,
|
||||
(GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels))
|
||||
COGL_FEATURE_FUNCTION (void, glTexSubImage3D,
|
||||
(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLenum type, const GLvoid* pixels))
|
||||
COGL_FEATURE_END ()
|
||||
|
@ -264,6 +264,9 @@ cogl_gles2_settings_equal (const CoglGles2WrapperSettings *a,
|
||||
int arg, n_args;
|
||||
GLenum func;
|
||||
|
||||
if (tex_env_a->texture_target != tex_env_b->texture_target)
|
||||
return FALSE;
|
||||
|
||||
if (tex_env_a->point_sprite_coords !=
|
||||
tex_env_b->point_sprite_coords)
|
||||
return FALSE;
|
||||
@ -407,7 +410,12 @@ cogl_gles2_add_texture_lookup (int unit,
|
||||
{
|
||||
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
|
||||
|
||||
g_string_append_printf (shader_source, "texture2D (texture_unit[%d], ", unit);
|
||||
if (w->settings.tex_env[unit].texture_target == GL_TEXTURE_3D_OES)
|
||||
g_string_append_printf (shader_source, "texture3D (texture_unit[%d], ",
|
||||
unit);
|
||||
else
|
||||
g_string_append_printf (shader_source, "texture2D (texture_unit[%d], ",
|
||||
unit);
|
||||
|
||||
/* If point sprite coord generation is being used then divert to the
|
||||
built-in varying var for that instead of the texture
|
||||
@ -1476,6 +1484,7 @@ _cogl_wrap_glEnable (GLenum cap)
|
||||
switch (cap)
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_TEXTURE_3D_OES:
|
||||
if (!COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units,
|
||||
w->active_texture_unit))
|
||||
{
|
||||
@ -1484,6 +1493,12 @@ _cogl_wrap_glEnable (GLenum cap)
|
||||
TRUE);
|
||||
w->settings_dirty = TRUE;
|
||||
}
|
||||
/* Keep track of the last enabled texture unit */
|
||||
if (w->settings.tex_env[w->active_texture_unit].texture_target != cap)
|
||||
{
|
||||
w->settings.tex_env[w->active_texture_unit].texture_target = cap;
|
||||
w->settings_dirty = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_FOG:
|
||||
@ -1507,8 +1522,12 @@ _cogl_wrap_glDisable (GLenum cap)
|
||||
switch (cap)
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_TEXTURE_3D_OES:
|
||||
/* If this was the last enabled texture target then we'll
|
||||
completely disable the unit */
|
||||
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units,
|
||||
w->active_texture_unit))
|
||||
w->active_texture_unit) &&
|
||||
w->settings.tex_env[w->active_texture_unit].texture_target == cap)
|
||||
{
|
||||
COGL_GLES2_TEXTURE_UNIT_SET_ENABLED (w->settings.texture_units,
|
||||
w->active_texture_unit,
|
||||
|
@ -128,6 +128,10 @@ struct _CoglGles2WrapperTexEnv
|
||||
GLfloat texture_combine_constant[4];
|
||||
|
||||
GLboolean point_sprite_coords;
|
||||
|
||||
/* Texture target that was last enabled for this unit. This assumes
|
||||
that there can only be one target enabled per unit */
|
||||
GLenum texture_target;
|
||||
};
|
||||
|
||||
/* NB: We get a copy of this for each fragment/vertex
|
||||
|
@ -48,6 +48,16 @@
|
||||
|
||||
#include "cogl-gles2-wrapper.h"
|
||||
|
||||
#define glTexImage3D ctx->drv.pf_glTexImage3D
|
||||
#define glTexSubImage3D ctx->drv.pf_glTexSubImage3D
|
||||
|
||||
#ifndef GL_TEXTURE_3D
|
||||
#define GL_TEXTURE_3D 0x806F
|
||||
#endif
|
||||
#ifndef GL_MAX_3D_TEXTURE_SIZE_OES
|
||||
#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
|
||||
#endif
|
||||
|
||||
void
|
||||
_cogl_texture_driver_gen (GLenum gl_target,
|
||||
GLsizei n,
|
||||
@ -63,15 +73,15 @@ _cogl_texture_driver_gen (GLenum gl_target,
|
||||
|
||||
switch (gl_target)
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
/* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
|
||||
GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
|
||||
break;
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_TEXTURE_3D:
|
||||
/* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
|
||||
GE( glTexParameteri (gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,6 +202,97 @@ _cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
||||
g_free (bmp.data);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
|
||||
GLuint gl_handle,
|
||||
gboolean is_foreign,
|
||||
GLint height,
|
||||
GLint depth,
|
||||
CoglBitmap *source_bmp,
|
||||
GLint internal_gl_format,
|
||||
GLuint source_gl_format,
|
||||
GLuint source_gl_type)
|
||||
{
|
||||
int bpp = _cogl_get_format_bpp (source_bmp->format);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||
|
||||
/* If the rowstride or image height can't be specified with just
|
||||
GL_ALIGNMENT alone then we need to copy the bitmap because there
|
||||
is no GL_ROW_LENGTH */
|
||||
if (source_bmp->rowstride / bpp != source_bmp->width ||
|
||||
height != source_bmp->height / depth)
|
||||
{
|
||||
int image_height = source_bmp->height / depth;
|
||||
int i;
|
||||
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (source_bmp->width * bpp,
|
||||
bpp);
|
||||
|
||||
/* Initialize the texture with empty data and then upload each
|
||||
image with a sub-region update */
|
||||
|
||||
GE( glTexImage3D (gl_target,
|
||||
0, /* level */
|
||||
internal_gl_format,
|
||||
source_bmp->width,
|
||||
height,
|
||||
depth,
|
||||
0,
|
||||
source_gl_format,
|
||||
source_gl_type,
|
||||
NULL) );
|
||||
|
||||
for (i = 0; i < depth; i++)
|
||||
{
|
||||
CoglBitmap bmp = *source_bmp;
|
||||
|
||||
bmp.rowstride = bpp * bmp.width;
|
||||
bmp.height = height;
|
||||
bmp.data = g_malloc (bmp.rowstride * bmp.height);
|
||||
|
||||
_cogl_bitmap_copy_subregion (source_bmp,
|
||||
&bmp,
|
||||
0, image_height * i,
|
||||
0, 0,
|
||||
bmp.width,
|
||||
bmp.height);
|
||||
|
||||
GE( glTexSubImage3D (gl_target,
|
||||
0, /* level */
|
||||
0, /* xoffset */
|
||||
0, /* yoffset */
|
||||
i, /* zoffset */
|
||||
bmp.width, /* width */
|
||||
height, /* height */
|
||||
1, /* depth */
|
||||
source_gl_format,
|
||||
source_gl_type,
|
||||
bmp.data) );
|
||||
|
||||
g_free (bmp.data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (source_bmp->rowstride,
|
||||
bpp);
|
||||
|
||||
GE( glTexImage3D (gl_target,
|
||||
0, /* level */
|
||||
internal_gl_format,
|
||||
source_bmp->width,
|
||||
height,
|
||||
depth,
|
||||
0,
|
||||
source_gl_format,
|
||||
source_gl_type,
|
||||
source_bmp->data) );
|
||||
}
|
||||
}
|
||||
|
||||
/* NB: GLES doesn't support glGetTexImage2D, so cogl-texture will instead
|
||||
* fallback to a generic render + readpixels approach to downloading
|
||||
* texture data. (See _cogl_texture_draw_and_read() ) */
|
||||
@ -204,6 +305,24 @@ _cogl_texture_driver_gl_get_tex_image (GLenum gl_target,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_size_supported_3d (GLenum gl_target,
|
||||
GLenum gl_format,
|
||||
GLenum gl_type,
|
||||
int width,
|
||||
int height,
|
||||
int depth)
|
||||
{
|
||||
GLint max_size;
|
||||
|
||||
/* GLES doesn't support a proxy texture target so let's at least
|
||||
check whether the size is greater than
|
||||
GL_MAX_3D_TEXTURE_SIZE_OES */
|
||||
GE( glGetIntegerv (GL_MAX_3D_TEXTURE_SIZE_OES, &max_size) );
|
||||
|
||||
return width <= max_size && height <= max_size && depth <= max_size;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_size_supported (GLenum gl_target,
|
||||
GLenum gl_format,
|
||||
|
@ -60,6 +60,7 @@
|
||||
<xi:include href="xml/cogl.xml"/>
|
||||
<xi:include href="xml/cogl-color.xml"/>
|
||||
<xi:include href="xml/cogl-texture.xml"/>
|
||||
<xi:include href="xml/cogl-texture-3d.xml"/>
|
||||
<xi:include href="blend-strings.xml"/>
|
||||
<xi:include href="xml/cogl-material.xml"/>
|
||||
<xi:include href="xml/cogl-primitives.xml"/>
|
||||
|
@ -232,6 +232,14 @@ cogl_texture_set_region
|
||||
COGL_TEXTURE_MAX_WASTE
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>cogl-texture-3d</FILE>
|
||||
<TITLE>3D textures</TITLE>
|
||||
cogl_texture_3d_new_with_size
|
||||
cogl_texture_3d_new_from_data
|
||||
cogl_is_texture_3d
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>cogl-shaders</FILE>
|
||||
<TITLE>Shaders and Programmable Pipeline</TITLE>
|
||||
|
Loading…
Reference in New Issue
Block a user