mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 18:11:05 -05:00
cogl: Add an internal CoglTextureRectangle backend
This adds an internal rectangle texture backend which is mostly based on the CoglTexture2D backend. It will throw assert failures if any operations are attempted that rectangle textures don't support, such as mipmapping or hardware repeating.
This commit is contained in:
parent
fd3a3e93bf
commit
3a3d55cd88
@ -128,6 +128,8 @@ cogl_sources_c = \
|
||||
$(srcdir)/cogl-texture.c \
|
||||
$(srcdir)/cogl-texture-2d.c \
|
||||
$(srcdir)/cogl-texture-2d-sliced.c \
|
||||
$(srcdir)/cogl-texture-rectangle-private.h \
|
||||
$(srcdir)/cogl-texture-rectangle.c \
|
||||
$(srcdir)/cogl-atlas.h \
|
||||
$(srcdir)/cogl-atlas.c \
|
||||
$(srcdir)/cogl-atlas-texture-private.h \
|
||||
|
68
clutter/cogl/cogl/cogl-texture-rectangle-private.h
Normal file
68
clutter/cogl/cogl/cogl-texture-rectangle-private.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Copyright (C) 2009 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/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __COGL_TEXTURE_RECTANGLE_H
|
||||
#define __COGL_TEXTURE_RECTANGLE_H
|
||||
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-material-private.h"
|
||||
#include "cogl-texture-private.h"
|
||||
|
||||
#define COGL_TEXTURE_RECTANGLE(tex) ((CoglTextureRectangle *) tex)
|
||||
|
||||
typedef struct _CoglTextureRectangle CoglTextureRectangle;
|
||||
|
||||
struct _CoglTextureRectangle
|
||||
{
|
||||
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;
|
||||
GLenum min_filter;
|
||||
GLenum mag_filter;
|
||||
GLint wrap_mode_s;
|
||||
GLint wrap_mode_t;
|
||||
};
|
||||
|
||||
GQuark
|
||||
_cogl_handle_texture_rectangle_get_type (void);
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_rectangle_new_with_size (unsigned int width,
|
||||
unsigned int height,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format);
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_rectangle_new_from_bitmap (CoglHandle bmp_handle,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format);
|
||||
|
||||
#endif /* __COGL_TEXTURE_RECTANGLE_H */
|
662
clutter/cogl/cogl/cogl-texture-rectangle.c
Normal file
662
clutter/cogl/cogl/cogl-texture-rectangle.c
Normal file
@ -0,0 +1,662 @@
|
||||
/*
|
||||
* 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-rectangle-private.h"
|
||||
#include "cogl-texture-driver.h"
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-journal-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/* These aren't defined under GLES */
|
||||
#ifndef GL_TEXTURE_RECTANGLE_ARB
|
||||
#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
|
||||
#endif
|
||||
#ifndef GL_CLAMP
|
||||
#define GL_CLAMP 0x2900
|
||||
#endif
|
||||
#ifndef GL_CLAMP_TO_BORDER
|
||||
#define GL_CLAMP_TO_BORDER 0x812D
|
||||
#endif
|
||||
|
||||
static void _cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect);
|
||||
|
||||
COGL_TEXTURE_DEFINE (TextureRectangle, texture_rectangle);
|
||||
|
||||
static const CoglTextureVtable cogl_texture_rectangle_vtable;
|
||||
|
||||
typedef struct _CoglTextureRectangleManualRepeatData
|
||||
{
|
||||
CoglTextureRectangle *tex_rect;
|
||||
CoglTextureSliceCallback callback;
|
||||
void *user_data;
|
||||
} CoglTextureRectangleManualRepeatData;
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_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_rectangle_manual_repeat_cb (const float *coords,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTextureRectangleManualRepeatData *data = user_data;
|
||||
float slice_coords[4];
|
||||
|
||||
_cogl_texture_rectangle_wrap_coords (coords[0], coords[2],
|
||||
slice_coords + 0, slice_coords + 2);
|
||||
_cogl_texture_rectangle_wrap_coords (coords[1], coords[3],
|
||||
slice_coords + 1, slice_coords + 3);
|
||||
|
||||
slice_coords[0] *= data->tex_rect->width;
|
||||
slice_coords[1] *= data->tex_rect->height;
|
||||
slice_coords[2] *= data->tex_rect->width;
|
||||
slice_coords[3] *= data->tex_rect->height;
|
||||
|
||||
data->callback (COGL_TEXTURE (data->tex_rect),
|
||||
data->tex_rect->gl_texture,
|
||||
GL_TEXTURE_RECTANGLE_ARB,
|
||||
slice_coords,
|
||||
coords,
|
||||
data->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_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)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
||||
CoglTextureRectangleManualRepeatData data;
|
||||
|
||||
data.tex_rect = tex_rect;
|
||||
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_rectangle_manual_repeat_cb,
|
||||
virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2,
|
||||
&data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
can_use_wrap_mode (GLenum wrap_mode)
|
||||
{
|
||||
return (wrap_mode == GL_CLAMP ||
|
||||
wrap_mode == GL_CLAMP_TO_EDGE ||
|
||||
wrap_mode == GL_CLAMP_TO_BORDER);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_set_wrap_mode_parameters (CoglTexture *tex,
|
||||
GLenum wrap_mode_s,
|
||||
GLenum wrap_mode_t,
|
||||
GLenum wrap_mode_r)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
||||
|
||||
/* Only set the wrap mode if it's different from the current value
|
||||
to avoid too many GL calls. Texture rectangle doesn't make use of
|
||||
the r coordinate so we can ignore its wrap mode */
|
||||
if (tex_rect->wrap_mode_s != wrap_mode_s ||
|
||||
tex_rect->wrap_mode_t != wrap_mode_t)
|
||||
{
|
||||
g_assert (can_use_wrap_mode (wrap_mode_s));
|
||||
g_assert (can_use_wrap_mode (wrap_mode_t));
|
||||
|
||||
GE( _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_rect->gl_texture,
|
||||
FALSE) );
|
||||
GE( glTexParameteri (GL_TEXTURE_RECTANGLE_ARB,
|
||||
GL_TEXTURE_WRAP_S, wrap_mode_s) );
|
||||
GE( glTexParameteri (GL_TEXTURE_RECTANGLE_ARB,
|
||||
GL_TEXTURE_WRAP_T, wrap_mode_t) );
|
||||
|
||||
tex_rect->wrap_mode_s = wrap_mode_s;
|
||||
tex_rect->wrap_mode_t = wrap_mode_t;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect)
|
||||
{
|
||||
_cogl_delete_gl_texture (tex_rect->gl_texture);
|
||||
|
||||
/* Chain up */
|
||||
_cogl_texture_free (COGL_TEXTURE (tex_rect));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_rectangle_can_create (unsigned int width,
|
||||
unsigned int height,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_type;
|
||||
|
||||
if (!cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE))
|
||||
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 (GL_TEXTURE_RECTANGLE_ARB,
|
||||
gl_intformat,
|
||||
gl_type,
|
||||
width,
|
||||
height))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglTextureRectangle *
|
||||
_cogl_texture_rectangle_create_base (unsigned int width,
|
||||
unsigned int height,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect = g_new (CoglTextureRectangle, 1);
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_rect);
|
||||
|
||||
tex->vtable = &cogl_texture_rectangle_vtable;
|
||||
|
||||
tex_rect->width = width;
|
||||
tex_rect->height = height;
|
||||
|
||||
/* We default to GL_LINEAR for both filters */
|
||||
tex_rect->min_filter = GL_LINEAR;
|
||||
tex_rect->mag_filter = GL_LINEAR;
|
||||
|
||||
/* Wrap mode not yet set */
|
||||
tex_rect->wrap_mode_s = GL_FALSE;
|
||||
tex_rect->wrap_mode_t = GL_FALSE;
|
||||
|
||||
tex_rect->format = internal_format;
|
||||
|
||||
return tex_rect;
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_rectangle_new_with_size (unsigned int width,
|
||||
unsigned int height,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect;
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
|
||||
/* 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_rectangle_can_create (width, height, internal_format))
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
internal_format = _cogl_pixel_format_to_gl (internal_format,
|
||||
&gl_intformat,
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
tex_rect = _cogl_texture_rectangle_create_base (width, height, flags,
|
||||
internal_format);
|
||||
|
||||
_cogl_texture_driver_gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture);
|
||||
GE( _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_rect->gl_texture,
|
||||
FALSE) );
|
||||
GE( glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_intformat,
|
||||
width, height, 0, gl_format, gl_type, NULL) );
|
||||
|
||||
return _cogl_texture_rectangle_handle_new (tex_rect);
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_rectangle_new_from_bitmap (CoglHandle bmp_handle,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect;
|
||||
CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
|
||||
CoglBitmap dst_bmp;
|
||||
gboolean dst_bmp_owner;
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
|
||||
g_return_val_if_fail (bmp_handle != COGL_INVALID_HANDLE, COGL_INVALID_HANDLE);
|
||||
|
||||
internal_format = _cogl_texture_determine_internal_format (bmp->format,
|
||||
internal_format);
|
||||
|
||||
if (!_cogl_texture_rectangle_can_create (bmp->width, bmp->height,
|
||||
internal_format))
|
||||
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))
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
tex_rect = _cogl_texture_rectangle_create_base (bmp->width,
|
||||
bmp->height,
|
||||
flags,
|
||||
internal_format);
|
||||
|
||||
_cogl_texture_driver_gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture);
|
||||
_cogl_texture_driver_upload_to_gl (GL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_rect->gl_texture,
|
||||
FALSE,
|
||||
&dst_bmp,
|
||||
gl_intformat,
|
||||
gl_format,
|
||||
gl_type);
|
||||
|
||||
tex_rect->gl_format = gl_intformat;
|
||||
|
||||
if (dst_bmp_owner)
|
||||
g_free (dst_bmp.data);
|
||||
|
||||
return _cogl_texture_rectangle_handle_new (tex_rect);
|
||||
}
|
||||
|
||||
static int
|
||||
_cogl_texture_rectangle_get_max_waste (CoglTexture *tex)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_rectangle_is_sliced (CoglTexture *tex)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_rectangle_can_hardware_repeat (CoglTexture *tex)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_transform_coords_to_gl (CoglTexture *tex,
|
||||
float *s,
|
||||
float *t)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
||||
|
||||
*s *= tex_rect->width;
|
||||
*t *= tex_rect->height;
|
||||
}
|
||||
|
||||
static CoglTransformResult
|
||||
_cogl_texture_rectangle_transform_quad_coords_to_gl (CoglTexture *tex,
|
||||
float *coords)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
||||
gboolean need_repeat = FALSE;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (coords[i] < 0.0f || coords[i] > 1.0f)
|
||||
need_repeat = TRUE;
|
||||
coords[i] *= (i & 1) ? tex_rect->height : tex_rect->width;
|
||||
}
|
||||
|
||||
return (need_repeat ? COGL_TRANSFORM_SOFTWARE_REPEAT
|
||||
: COGL_TRANSFORM_NO_REPEAT);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_rectangle_get_gl_texture (CoglTexture *tex,
|
||||
GLuint *out_gl_handle,
|
||||
GLenum *out_gl_target)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
||||
|
||||
if (out_gl_handle)
|
||||
*out_gl_handle = tex_rect->gl_texture;
|
||||
|
||||
if (out_gl_target)
|
||||
*out_gl_target = GL_TEXTURE_RECTANGLE_ARB;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_set_filters (CoglTexture *tex,
|
||||
GLenum min_filter,
|
||||
GLenum mag_filter)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
||||
|
||||
if (min_filter == tex_rect->min_filter
|
||||
&& mag_filter == tex_rect->mag_filter)
|
||||
return;
|
||||
|
||||
/* Rectangle textures don't support mipmapping */
|
||||
g_assert (min_filter == GL_LINEAR || min_filter == GL_NEAREST);
|
||||
|
||||
/* Store new values */
|
||||
tex_rect->min_filter = min_filter;
|
||||
tex_rect->mag_filter = mag_filter;
|
||||
|
||||
/* Apply new filters to the texture */
|
||||
GE( _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_rect->gl_texture,
|
||||
FALSE) );
|
||||
GE( glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
|
||||
mag_filter) );
|
||||
GE( glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
|
||||
min_filter) );
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_pre_paint (CoglTexture *tex,
|
||||
CoglTexturePrePaintFlags flags)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Rectangle textures don't support mipmaps */
|
||||
g_assert ((flags & COGL_TEXTURE_NEEDS_MIPMAP) == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_ensure_non_quad_rendering (CoglTexture *tex)
|
||||
{
|
||||
/* Nothing needs to be done */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_rectangle_set_region (CoglTexture *tex,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int dst_width,
|
||||
unsigned int dst_height,
|
||||
int width,
|
||||
int height,
|
||||
CoglPixelFormat format,
|
||||
unsigned int rowstride,
|
||||
const guint8 *data)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
||||
int bpp;
|
||||
CoglBitmap source_bmp;
|
||||
CoglBitmap tmp_bmp;
|
||||
gboolean tmp_bmp_owner = FALSE;
|
||||
GLenum closest_gl_format;
|
||||
GLenum closest_gl_type;
|
||||
|
||||
/* Check for valid format */
|
||||
if (format == COGL_PIXEL_FORMAT_ANY)
|
||||
return FALSE;
|
||||
|
||||
/* Shortcut out early if the image is empty */
|
||||
if (width == 0 || height == 0)
|
||||
return TRUE;
|
||||
|
||||
/* Init source bitmap */
|
||||
source_bmp.width = width;
|
||||
source_bmp.height = height;
|
||||
source_bmp.format = format;
|
||||
source_bmp.data = (guint8 *)data;
|
||||
|
||||
/* Rowstride from width if none specified */
|
||||
bpp = _cogl_get_format_bpp (format);
|
||||
source_bmp.rowstride = (rowstride == 0) ? width * bpp : rowstride;
|
||||
|
||||
/* Prepare the bitmap so that it will do the premultiplication
|
||||
conversion */
|
||||
_cogl_texture_prepare_for_upload (&source_bmp,
|
||||
tex_rect->format,
|
||||
NULL,
|
||||
&tmp_bmp,
|
||||
&tmp_bmp_owner,
|
||||
NULL,
|
||||
&closest_gl_format,
|
||||
&closest_gl_type);
|
||||
|
||||
/* Send data to GL */
|
||||
_cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_rect->gl_texture,
|
||||
FALSE,
|
||||
src_x, src_y,
|
||||
dst_x, dst_y,
|
||||
dst_width, dst_height,
|
||||
&tmp_bmp,
|
||||
closest_gl_format,
|
||||
closest_gl_type);
|
||||
|
||||
/* Free data if owner */
|
||||
if (tmp_bmp_owner)
|
||||
g_free (tmp_bmp.data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
_cogl_texture_rectangle_get_data (CoglTexture *tex,
|
||||
CoglPixelFormat format,
|
||||
unsigned int rowstride,
|
||||
guint8 *data)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
||||
int bpp;
|
||||
int byte_size;
|
||||
CoglPixelFormat closest_format;
|
||||
int closest_bpp;
|
||||
GLenum closest_gl_format;
|
||||
GLenum closest_gl_type;
|
||||
CoglBitmap target_bmp;
|
||||
CoglBitmap new_bmp;
|
||||
gboolean success;
|
||||
guint8 *src;
|
||||
guint8 *dst;
|
||||
int y;
|
||||
|
||||
/* Default to internal format if none specified */
|
||||
if (format == COGL_PIXEL_FORMAT_ANY)
|
||||
format = tex_rect->format;
|
||||
|
||||
/* Rowstride from texture width if none specified */
|
||||
bpp = _cogl_get_format_bpp (format);
|
||||
if (rowstride == 0)
|
||||
rowstride = tex_rect->width * bpp;
|
||||
|
||||
/* Return byte size if only that requested */
|
||||
byte_size = tex_rect->height * rowstride;
|
||||
if (data == NULL)
|
||||
return byte_size;
|
||||
|
||||
closest_format =
|
||||
_cogl_texture_driver_find_best_gl_get_data_format (format,
|
||||
&closest_gl_format,
|
||||
&closest_gl_type);
|
||||
closest_bpp = _cogl_get_format_bpp (closest_format);
|
||||
|
||||
target_bmp.width = tex_rect->width;
|
||||
target_bmp.height = tex_rect->height;
|
||||
|
||||
/* Is the requested format supported? */
|
||||
if (closest_format == format)
|
||||
{
|
||||
/* Target user data directly */
|
||||
target_bmp.format = format;
|
||||
target_bmp.rowstride = rowstride;
|
||||
target_bmp.data = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Target intermediate buffer */
|
||||
target_bmp.format = closest_format;
|
||||
target_bmp.rowstride = target_bmp.width * closest_bpp;
|
||||
target_bmp.data = g_malloc (target_bmp.height * target_bmp.rowstride);
|
||||
}
|
||||
|
||||
_cogl_texture_driver_prep_gl_for_pixels_download (target_bmp.rowstride,
|
||||
closest_bpp);
|
||||
|
||||
GE( _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_rect->gl_texture,
|
||||
FALSE) );
|
||||
if (!_cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_RECTANGLE_ARB,
|
||||
closest_gl_format,
|
||||
closest_gl_type,
|
||||
target_bmp.data))
|
||||
{
|
||||
/* XXX: In some cases _cogl_texture_rectangle_download_from_gl may
|
||||
* fail to read back the texture data; such as for GLES which doesn't
|
||||
* support glGetTexImage, so here we fallback to drawing the texture
|
||||
* and reading the pixels from the framebuffer. */
|
||||
_cogl_texture_draw_and_read (tex, &target_bmp,
|
||||
closest_gl_format,
|
||||
closest_gl_type);
|
||||
}
|
||||
|
||||
/* Was intermediate used? */
|
||||
if (closest_format != format)
|
||||
{
|
||||
/* Convert to requested format */
|
||||
success = _cogl_bitmap_convert_format_and_premult (&target_bmp,
|
||||
&new_bmp,
|
||||
format);
|
||||
|
||||
/* Free intermediate data and return if failed */
|
||||
g_free (target_bmp.data);
|
||||
if (!success)
|
||||
return 0;
|
||||
|
||||
/* Copy to user buffer */
|
||||
for (y = 0; y < new_bmp.height; ++y)
|
||||
{
|
||||
src = new_bmp.data + y * new_bmp.rowstride;
|
||||
dst = data + y * rowstride;
|
||||
memcpy (dst, src, new_bmp.width);
|
||||
}
|
||||
|
||||
/* Free converted data */
|
||||
g_free (new_bmp.data);
|
||||
}
|
||||
|
||||
return byte_size;
|
||||
}
|
||||
|
||||
static CoglPixelFormat
|
||||
_cogl_texture_rectangle_get_format (CoglTexture *tex)
|
||||
{
|
||||
return COGL_TEXTURE_RECTANGLE (tex)->format;
|
||||
}
|
||||
|
||||
static GLenum
|
||||
_cogl_texture_rectangle_get_gl_format (CoglTexture *tex)
|
||||
{
|
||||
return COGL_TEXTURE_RECTANGLE (tex)->gl_format;
|
||||
}
|
||||
|
||||
static int
|
||||
_cogl_texture_rectangle_get_width (CoglTexture *tex)
|
||||
{
|
||||
return COGL_TEXTURE_RECTANGLE (tex)->width;
|
||||
}
|
||||
|
||||
static int
|
||||
_cogl_texture_rectangle_get_height (CoglTexture *tex)
|
||||
{
|
||||
return COGL_TEXTURE_RECTANGLE (tex)->height;
|
||||
}
|
||||
|
||||
static const CoglTextureVtable
|
||||
cogl_texture_rectangle_vtable =
|
||||
{
|
||||
_cogl_texture_rectangle_set_region,
|
||||
_cogl_texture_rectangle_get_data,
|
||||
_cogl_texture_rectangle_foreach_sub_texture_in_region,
|
||||
_cogl_texture_rectangle_get_max_waste,
|
||||
_cogl_texture_rectangle_is_sliced,
|
||||
_cogl_texture_rectangle_can_hardware_repeat,
|
||||
_cogl_texture_rectangle_transform_coords_to_gl,
|
||||
_cogl_texture_rectangle_transform_quad_coords_to_gl,
|
||||
_cogl_texture_rectangle_get_gl_texture,
|
||||
_cogl_texture_rectangle_set_filters,
|
||||
_cogl_texture_rectangle_pre_paint,
|
||||
_cogl_texture_rectangle_ensure_non_quad_rendering,
|
||||
_cogl_texture_rectangle_set_wrap_mode_parameters,
|
||||
_cogl_texture_rectangle_get_format,
|
||||
_cogl_texture_rectangle_get_gl_format,
|
||||
_cogl_texture_rectangle_get_width,
|
||||
_cogl_texture_rectangle_get_height,
|
||||
NULL /* is_foreign */
|
||||
};
|
@ -312,6 +312,13 @@ COGL_FEATURE_FUNCTION (void, glDeleteBuffers,
|
||||
const GLuint *buffers))
|
||||
COGL_FEATURE_END ()
|
||||
|
||||
COGL_FEATURE_BEGIN (texture_rectangle, 255, 255,
|
||||
"ARB\0",
|
||||
"texture_rectangle\0",
|
||||
COGL_FEATURE_TEXTURE_RECTANGLE,
|
||||
0)
|
||||
COGL_FEATURE_END ()
|
||||
|
||||
/* Cogl requires OpenGL 1.2 so we assume these functions are always
|
||||
available and don't bother setting any feature flags. We still have
|
||||
to fetch the function pointers though because under Windows you can
|
||||
|
@ -70,6 +70,11 @@ _cogl_texture_driver_gen (GLenum gl_target,
|
||||
GE( glTexParameteri (GL_TEXTURE_2D, 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;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
@ -201,26 +206,28 @@ _cogl_texture_driver_size_supported (GLenum gl_target,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (gl_target == GL_TEXTURE_2D)
|
||||
{
|
||||
/* Proxy texture allows for a quick check for supported size */
|
||||
GLenum proxy_target;
|
||||
GLint new_width = 0;
|
||||
|
||||
GLint new_width = 0;
|
||||
|
||||
GE( glTexImage2D (GL_PROXY_TEXTURE_2D, 0, GL_RGBA,
|
||||
width, height, 0 /* border */,
|
||||
gl_format, gl_type, NULL) );
|
||||
|
||||
GE( glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0,
|
||||
GL_TEXTURE_WIDTH, &new_width) );
|
||||
|
||||
return new_width != 0;
|
||||
}
|
||||
if (gl_target == GL_TEXTURE_2D)
|
||||
proxy_target = GL_PROXY_TEXTURE_2D;
|
||||
#if HAVE_COGL_GL
|
||||
else if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
proxy_target = GL_PROXY_TEXTURE_RECTANGLE_ARB;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* not used */
|
||||
return 0;
|
||||
}
|
||||
/* Unknown target, assume it's not supported */
|
||||
return FALSE;
|
||||
|
||||
/* Proxy texture allows for a quick check for supported size */
|
||||
GE( glTexImage2D (proxy_target, 0, GL_RGBA,
|
||||
width, height, 0 /* border */,
|
||||
gl_format, gl_type, NULL) );
|
||||
|
||||
GE( glGetTexLevelParameteriv (proxy_target, 0,
|
||||
GL_TEXTURE_WIDTH, &new_width) );
|
||||
|
||||
return new_width != 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user