mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 01:20:42 -05:00
[cogl-texture] Split CoglTexture into an abstract class + CoglTexture2dSliced
cogl-texture-2d-sliced provides an implementation of CoglTexture and this seperation lays the foundation for potentially supporting atlas textures, pixmap textures (as in GLX_EXT_texture_from_pixmap) and fast-path GL_TEXTURE_{1D,2D,3D,RECTANGLE} textures in a maintainable fashion.
This commit is contained in:
parent
c40d5ae9ea
commit
65015a137e
@ -114,8 +114,10 @@ libclutter_cogl_la_SOURCES = \
|
||||
cogl-blend-string.h \
|
||||
cogl-debug.c \
|
||||
cogl-texture-private.h \
|
||||
cogl-texture-2d-sliced-private.h \
|
||||
cogl-texture-driver.h \
|
||||
cogl-texture.c \
|
||||
cogl-texture-2d-sliced.c \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST += stb_image.c cogl-enum-types.h.in cogl-enum-types.c.in
|
||||
|
@ -100,6 +100,8 @@ cogl_create_context (void)
|
||||
_context->quad_indices_short = COGL_INVALID_HANDLE;
|
||||
_context->quad_indices_short_len = 0;
|
||||
|
||||
_context->texture_download_material = COGL_INVALID_HANDLE;
|
||||
|
||||
/* Initialise the clip stack */
|
||||
_cogl_clip_stack_state_init ();
|
||||
|
||||
|
@ -115,6 +115,8 @@ typedef struct
|
||||
guint viewport_width;
|
||||
guint viewport_height;
|
||||
|
||||
CoglHandle texture_download_material;
|
||||
|
||||
CoglContextDriver drv;
|
||||
} CoglContext;
|
||||
|
||||
|
@ -81,7 +81,7 @@ typedef struct _CoglHandleObject
|
||||
\
|
||||
static CoglHandleClass _cogl_##type_name##_class; \
|
||||
\
|
||||
static GQuark \
|
||||
GQuark \
|
||||
_cogl_handle_##type_name##_get_type (void) \
|
||||
{ \
|
||||
static GQuark type = 0; \
|
||||
@ -93,7 +93,7 @@ _cogl_handle_##type_name##_get_type (void) \
|
||||
static CoglHandle \
|
||||
_cogl_##type_name##_handle_new (Cogl##TypeName *new_obj) \
|
||||
{ \
|
||||
CoglHandleObject *obj = &new_obj->_parent; \
|
||||
CoglHandleObject *obj = (CoglHandleObject *)&new_obj->_parent;\
|
||||
obj->ref_count = 1; \
|
||||
\
|
||||
obj->klass = &_cogl_##type_name##_class; \
|
||||
|
191
cogl/cogl-texture-2d-sliced-private.h
Normal file
191
cogl/cogl-texture-2d-sliced-private.h
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Copyright (C) 2007,2008,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, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __COGL_TEXTURE_2D_SLICED_H
|
||||
#define __COGL_TEXTURE_2D_SLICED_H
|
||||
|
||||
#include "cogl-bitmap-private.h"
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-material-private.h"
|
||||
#include "cogl-texture-private.h"
|
||||
|
||||
#define COGL_TEXTURE_2D_SLICED(tex) ((CoglTexture2DSliced *)tex)
|
||||
|
||||
typedef struct _CoglTexture2DSliced CoglTexture2DSliced;
|
||||
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
|
||||
typedef struct _CoglSpanIter CoglSpanIter;
|
||||
typedef struct _CoglTexturePixel CoglTexturePixel;
|
||||
|
||||
struct _CoglTexSliceSpan
|
||||
{
|
||||
int start;
|
||||
int size;
|
||||
int waste;
|
||||
};
|
||||
|
||||
struct _CoglSpanIter
|
||||
{
|
||||
gint index;
|
||||
GArray *array;
|
||||
CoglTexSliceSpan *span;
|
||||
float pos;
|
||||
float next_pos;
|
||||
float origin;
|
||||
float cover_start;
|
||||
float cover_end;
|
||||
float intersect_start;
|
||||
float intersect_end;
|
||||
float intersect_start_local;
|
||||
float intersect_end_local;
|
||||
gboolean intersects;
|
||||
gboolean flipped;
|
||||
};
|
||||
|
||||
/* This is used to store the first pixel of each slice. This is only
|
||||
used when glGenerateMipmap is not available */
|
||||
struct _CoglTexturePixel
|
||||
{
|
||||
/* We need to store the format of the pixel because we store the
|
||||
data in the source format which might end up being different for
|
||||
each slice if a subregion is updated with a different format */
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
guint8 data[4];
|
||||
};
|
||||
|
||||
struct _CoglTexture2DSliced
|
||||
{
|
||||
CoglTexture _parent;
|
||||
GArray *slice_x_spans;
|
||||
GArray *slice_y_spans;
|
||||
GArray *slice_gl_handles;
|
||||
gint max_waste;
|
||||
|
||||
/* This holds a copy of the first pixel in each slice. It is only
|
||||
used to force an automatic update of the mipmaps when
|
||||
glGenerateMipmap is not available. */
|
||||
CoglTexturePixel *first_pixels;
|
||||
};
|
||||
|
||||
GQuark
|
||||
_cogl_handle_texture_2d_sliced_get_type (void);
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_2d_sliced_new_with_size (unsigned int width,
|
||||
unsigned int height,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format);
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_2d_sliced_new_from_file (const gchar *filename,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format,
|
||||
GError **error);
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle,
|
||||
GLenum gl_target,
|
||||
GLuint width,
|
||||
GLuint height,
|
||||
GLuint x_pot_waste,
|
||||
GLuint y_pot_waste,
|
||||
CoglPixelFormat format);
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_2d_sliced_new_from_data (unsigned int width,
|
||||
unsigned int height,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat format,
|
||||
CoglPixelFormat internal_format,
|
||||
unsigned int rowstride,
|
||||
const guint8 *data);
|
||||
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_2d_sliced_new_from_bitmap (CoglHandle bmp_handle,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_2d_sliced_set_region (CoglHandle handle,
|
||||
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);
|
||||
|
||||
int
|
||||
_cogl_texture_2d_sliced_get_data (CoglHandle handle,
|
||||
CoglPixelFormat format,
|
||||
unsigned int rowstride,
|
||||
guint8 *data);
|
||||
|
||||
void
|
||||
_cogl_texture_2d_sliced_foreach_sub_texture_in_region (
|
||||
CoglTexture2DSliced *tex_2ds,
|
||||
float virtual_tx_1,
|
||||
float virtual_ty_1,
|
||||
float virtual_tx_2,
|
||||
float virtual_ty_2,
|
||||
CoglTextureSliceCallback callback,
|
||||
void *user_data);
|
||||
|
||||
gint
|
||||
_cogl_texture_2d_sliced_get_max_waste (CoglHandle handle);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_2d_sliced_is_sliced (CoglHandle handle);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_2d_sliced_can_hardware_repeat (CoglHandle handle);
|
||||
|
||||
void
|
||||
_cogl_texture_2d_sliced_transform_coords_to_gl (CoglTexture2DSliced *tex_2ds,
|
||||
float *s,
|
||||
float *t);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_2d_sliced_get_gl_texture (CoglHandle handle,
|
||||
GLuint *out_gl_handle,
|
||||
GLenum *out_gl_target);
|
||||
|
||||
void
|
||||
_cogl_texture_2d_sliced_set_filters (CoglHandle handle,
|
||||
GLenum min_filter,
|
||||
GLenum mag_filter);
|
||||
|
||||
void
|
||||
_cogl_texture_2d_sliced_ensure_mipmaps (CoglHandle handle);
|
||||
|
||||
void
|
||||
_cogl_texture_2d_sliced_set_wrap_mode_parameter (CoglTexture2DSliced *tex_2ds,
|
||||
GLenum wrap_mode);
|
||||
|
||||
|
||||
#endif /* __COGL_TEXTURE_2D_SLICED_H */
|
1871
cogl/cogl-texture-2d-sliced.c
Normal file
1871
cogl/cogl-texture-2d-sliced.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -91,6 +91,18 @@ _cogl_texture_driver_download_from_gl (CoglTexture *tex,
|
||||
GLuint target_gl_format,
|
||||
GLuint target_gl_type);
|
||||
|
||||
/*
|
||||
* This driver abstraction is needed because GLES doesn't support glGetTexImage
|
||||
* (). On GLES this currently just returns FALSE which will lead to a generic
|
||||
* fallback path being used that simply renders the texture and reads it back
|
||||
* from the framebuffer. (See _cogl_texture_draw_and_read () )
|
||||
*/
|
||||
gboolean
|
||||
_cogl_texture_driver_gl_get_tex_image (GLenum gl_target,
|
||||
GLenum dest_gl_format,
|
||||
GLenum dest_gl_type,
|
||||
guint8 *dest);
|
||||
|
||||
/*
|
||||
* It may depend on the driver as to what texture sizes are supported...
|
||||
*/
|
||||
|
@ -28,72 +28,31 @@
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-material-private.h"
|
||||
|
||||
#define COGL_TEXTURE(tex) ((CoglTexture *)(tex))
|
||||
|
||||
typedef struct _CoglTexture CoglTexture;
|
||||
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
|
||||
typedef struct _CoglSpanIter CoglSpanIter;
|
||||
typedef struct _CoglTexturePixel CoglTexturePixel;
|
||||
|
||||
struct _CoglTexSliceSpan
|
||||
typedef enum _CoglTextureType
|
||||
{
|
||||
gint start;
|
||||
gint size;
|
||||
gint waste;
|
||||
};
|
||||
|
||||
struct _CoglSpanIter
|
||||
{
|
||||
gint index;
|
||||
GArray *array;
|
||||
CoglTexSliceSpan *span;
|
||||
float pos;
|
||||
float next_pos;
|
||||
float origin;
|
||||
float cover_start;
|
||||
float cover_end;
|
||||
float intersect_start;
|
||||
float intersect_end;
|
||||
float intersect_start_local;
|
||||
float intersect_end_local;
|
||||
gboolean intersects;
|
||||
gboolean flipped;
|
||||
};
|
||||
|
||||
/* This is used to store the first pixel of each slice. This is only
|
||||
used when glGenerateMipmap is not available */
|
||||
struct _CoglTexturePixel
|
||||
{
|
||||
/* We need to store the format of the pixel because we store the
|
||||
data in the source format which might end up being different for
|
||||
each slice if a subregion is updated with a different format */
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
guint8 data[4];
|
||||
};
|
||||
COGL_TEXTURE_TYPE_2D_SLICED
|
||||
} CoglTextureType;
|
||||
|
||||
struct _CoglTexture
|
||||
{
|
||||
CoglHandleObject _parent;
|
||||
CoglTextureType type;
|
||||
CoglBitmap bitmap;
|
||||
gboolean bitmap_owner;
|
||||
GLenum gl_target;
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
GArray *slice_x_spans;
|
||||
GArray *slice_y_spans;
|
||||
GArray *slice_gl_handles;
|
||||
gint max_waste;
|
||||
GLenum min_filter;
|
||||
GLenum mag_filter;
|
||||
gboolean is_foreign;
|
||||
GLint wrap_mode;
|
||||
gboolean auto_mipmap;
|
||||
gboolean mipmaps_dirty;
|
||||
|
||||
/* This holds a copy of the first pixel in each slice. It is only
|
||||
used to force an automatic update of the mipmaps when
|
||||
glGenerateMipmap is not available. */
|
||||
CoglTexturePixel *first_pixels;
|
||||
};
|
||||
|
||||
/* To improve batching of geometry when submitting vertices to OpenGL we
|
||||
@ -117,9 +76,6 @@ typedef void (*CoglTextureSliceCallback) (CoglHandle handle,
|
||||
float *virtual_coords,
|
||||
void *user_data);
|
||||
|
||||
CoglTexture*
|
||||
_cogl_texture_pointer_from_handle (CoglHandle handle);
|
||||
|
||||
void
|
||||
_cogl_texture_foreach_sub_texture_in_region (CoglHandle handle,
|
||||
float virtual_tx_1,
|
||||
@ -151,10 +107,34 @@ _cogl_texture_set_filters (CoglHandle handle,
|
||||
void
|
||||
_cogl_texture_ensure_mipmaps (CoglHandle handle);
|
||||
|
||||
|
||||
/* Functions currently only used by CoglTexture implementations or
|
||||
* drivers... */
|
||||
|
||||
void
|
||||
_cogl_texture_free (CoglTexture *tex);
|
||||
|
||||
void
|
||||
_cogl_texture_bitmap_free (CoglTexture *tex);
|
||||
|
||||
void
|
||||
_cogl_texture_bitmap_swap (CoglTexture *tex,
|
||||
CoglBitmap *new_bitmap);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_bitmap_prepare (CoglTexture *tex,
|
||||
CoglPixelFormat internal_format);
|
||||
|
||||
void
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_upload (int pixels_rowstride);
|
||||
|
||||
void
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_download (int pixels_rowstride);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_draw_and_read (CoglTexture *tex,
|
||||
CoglBitmap *target_bmp,
|
||||
GLuint target_gl_format,
|
||||
GLuint target_gl_type);
|
||||
|
||||
#endif /* __COGL_TEXTURE_PRIVATE_H */
|
||||
|
1954
cogl/cogl-texture.c
1954
cogl/cogl-texture.c
File diff suppressed because it is too large
Load Diff
@ -135,95 +135,16 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglTexture *tex,
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_download_from_gl (CoglTexture *tex,
|
||||
CoglBitmap *target_bmp,
|
||||
GLuint target_gl_format,
|
||||
GLuint target_gl_type)
|
||||
_cogl_texture_driver_gl_get_tex_image (GLenum gl_target,
|
||||
GLenum dest_gl_format,
|
||||
GLenum dest_gl_type,
|
||||
guint8 *dest)
|
||||
{
|
||||
CoglTexSliceSpan *x_span;
|
||||
CoglTexSliceSpan *y_span;
|
||||
GLuint gl_handle;
|
||||
gint bpp;
|
||||
gint x,y;
|
||||
CoglBitmap slice_bmp;
|
||||
|
||||
bpp = _cogl_get_format_bpp (target_bmp->format);
|
||||
|
||||
/* Iterate vertical slices */
|
||||
for (y = 0; y < tex->slice_y_spans->len; ++y)
|
||||
{
|
||||
y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, y);
|
||||
|
||||
/* Iterate horizontal slices */
|
||||
for (x = 0; x < tex->slice_x_spans->len; ++x)
|
||||
{
|
||||
/*if (x != 0 || y != 1) continue;*/
|
||||
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x);
|
||||
|
||||
/* Pick the gl texture object handle */
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
|
||||
y * tex->slice_x_spans->len + x);
|
||||
|
||||
/* If there's any waste we need to copy manually
|
||||
(no glGetTexSubImage) */
|
||||
|
||||
if (y_span->waste != 0 || x_span->waste != 0)
|
||||
{
|
||||
/* Setup temp bitmap for slice subregion */
|
||||
slice_bmp.format = target_bmp->format;
|
||||
slice_bmp.width = x_span->size;
|
||||
slice_bmp.height = y_span->size;
|
||||
slice_bmp.rowstride = bpp * slice_bmp.width;
|
||||
slice_bmp.data = (guchar*) g_malloc (slice_bmp.rowstride *
|
||||
slice_bmp.height);
|
||||
|
||||
/* Setup gl alignment to 0,0 top-left corner */
|
||||
_cogl_texture_driver_prep_gl_for_pixels_download (
|
||||
slice_bmp.rowstride,
|
||||
bpp);
|
||||
|
||||
/* Download slice image data into temp bmp */
|
||||
GE( glBindTexture (tex->gl_target, gl_handle) );
|
||||
|
||||
GE (glGetTexImage (tex->gl_target,
|
||||
0, /* level */
|
||||
target_gl_format,
|
||||
target_gl_type,
|
||||
slice_bmp.data) );
|
||||
|
||||
/* Copy portion of slice from temp to target bmp */
|
||||
_cogl_bitmap_copy_subregion (&slice_bmp,
|
||||
target_bmp,
|
||||
0, 0,
|
||||
x_span->start,
|
||||
y_span->start,
|
||||
x_span->size - x_span->waste,
|
||||
y_span->size - y_span->waste);
|
||||
/* Free temp bitmap */
|
||||
g_free (slice_bmp.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLvoid *dst = target_bmp->data
|
||||
+ x_span->start * bpp
|
||||
+ y_span->start * target_bmp->rowstride;
|
||||
|
||||
_cogl_texture_driver_prep_gl_for_pixels_download (
|
||||
target_bmp->rowstride,
|
||||
bpp);
|
||||
|
||||
/* Download slice image data */
|
||||
GE( glBindTexture (tex->gl_target, gl_handle) );
|
||||
|
||||
GE( glGetTexImage (tex->gl_target,
|
||||
0, /* level */
|
||||
target_gl_format,
|
||||
target_gl_type,
|
||||
dst) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GE (glGetTexImage (gl_target,
|
||||
0, /* level */
|
||||
dest_gl_format,
|
||||
dest_gl_type,
|
||||
(GLvoid *)dest));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,6 @@
|
||||
void
|
||||
_cogl_create_context_driver (CoglContext *context)
|
||||
{
|
||||
context->drv.texture_download_material = COGL_INVALID_HANDLE;
|
||||
|
||||
/* Init the GLES2 wrapper */
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
cogl_gles2_wrapper_init (&context->drv.gles2);
|
||||
|
@ -29,8 +29,6 @@
|
||||
typedef struct _CoglContextDriver
|
||||
|
||||
{
|
||||
CoglHandle texture_download_material;
|
||||
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
CoglGles2Wrapper gles2;
|
||||
|
||||
|
@ -128,217 +128,16 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglTexture *tex,
|
||||
g_free (slice_bmp.data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_draw_and_read (CoglTexture *tex,
|
||||
CoglBitmap *target_bmp,
|
||||
GLint *viewport)
|
||||
{
|
||||
gint bpp;
|
||||
float rx1, ry1;
|
||||
float rx2, ry2;
|
||||
float tx1, ty1;
|
||||
float tx2, ty2;
|
||||
int bw, bh;
|
||||
CoglBitmap rect_bmp;
|
||||
CoglHandle handle;
|
||||
|
||||
handle = (CoglHandle) tex;
|
||||
bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);
|
||||
|
||||
ry1 = 0; ry2 = 0;
|
||||
ty1 = 0; ty2 = 0;
|
||||
|
||||
/* Walk Y axis until whole bitmap height consumed */
|
||||
for (bh = tex->bitmap.height; bh > 0; bh -= viewport[3])
|
||||
{
|
||||
/* Rectangle Y coords */
|
||||
ry1 = ry2;
|
||||
ry2 += (bh < viewport[3]) ? bh : viewport[3];
|
||||
|
||||
/* Normalized texture Y coords */
|
||||
ty1 = ty2;
|
||||
ty2 = (ry2 / (float)tex->bitmap.height);
|
||||
|
||||
rx1 = 0; rx2 = 0;
|
||||
tx1 = 0; tx2 = 0;
|
||||
|
||||
/* Walk X axis until whole bitmap width consumed */
|
||||
for (bw = tex->bitmap.width; bw > 0; bw-=viewport[2])
|
||||
{
|
||||
/* Rectangle X coords */
|
||||
rx1 = rx2;
|
||||
rx2 += (bw < viewport[2]) ? bw : viewport[2];
|
||||
|
||||
/* Normalized texture X coords */
|
||||
tx1 = tx2;
|
||||
tx2 = (rx2 / (float)tex->bitmap.width);
|
||||
|
||||
/* Draw a portion of texture */
|
||||
cogl_rectangle_with_texture_coords (0, 0,
|
||||
rx2 - rx1,
|
||||
ry2 - ry1,
|
||||
tx1, ty1,
|
||||
tx2, ty2);
|
||||
|
||||
/* Read into a temporary bitmap */
|
||||
rect_bmp.format = COGL_PIXEL_FORMAT_RGBA_8888;
|
||||
rect_bmp.width = rx2 - rx1;
|
||||
rect_bmp.height = ry2 - ry1;
|
||||
rect_bmp.rowstride = bpp * rect_bmp.width;
|
||||
rect_bmp.data = (guchar*) g_malloc (rect_bmp.rowstride *
|
||||
rect_bmp.height);
|
||||
|
||||
_cogl_texture_driver_prep_gl_for_pixels_download (rect_bmp.rowstride,
|
||||
bpp);
|
||||
GE( glReadPixels (viewport[0], viewport[1],
|
||||
rect_bmp.width,
|
||||
rect_bmp.height,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
rect_bmp.data) );
|
||||
|
||||
/* Copy to target bitmap */
|
||||
_cogl_bitmap_copy_subregion (&rect_bmp,
|
||||
target_bmp,
|
||||
0,0,
|
||||
rx1,ry1,
|
||||
rect_bmp.width,
|
||||
rect_bmp.height);
|
||||
|
||||
/* Free temp bitmap */
|
||||
g_free (rect_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() ) */
|
||||
gboolean
|
||||
_cogl_texture_driver_download_from_gl (CoglTexture *tex,
|
||||
CoglBitmap *target_bmp,
|
||||
GLuint target_gl_format,
|
||||
GLuint target_gl_type)
|
||||
_cogl_texture_driver_gl_get_tex_image (GLenum gl_target,
|
||||
GLenum dest_gl_format,
|
||||
GLenum dest_gl_type,
|
||||
guint8 *dest)
|
||||
{
|
||||
gint bpp;
|
||||
GLint viewport[4];
|
||||
CoglBitmap alpha_bmp;
|
||||
CoglHandle prev_source;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
|
||||
bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);
|
||||
|
||||
/* Viewport needs to have some size and be inside the window for this */
|
||||
GE( glGetIntegerv (GL_VIEWPORT, viewport) );
|
||||
|
||||
if (viewport[0] < 0 || viewport[1] < 0 ||
|
||||
viewport[2] <= 0 || viewport[3] <= 0)
|
||||
return FALSE;
|
||||
|
||||
/* Setup orthographic projection into current viewport
|
||||
(0,0 in bottom-left corner to draw the texture
|
||||
upside-down so we match the way glReadPixels works) */
|
||||
|
||||
_cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
|
||||
_cogl_current_matrix_push ();
|
||||
_cogl_current_matrix_identity ();
|
||||
|
||||
_cogl_current_matrix_ortho (0, (float)(viewport[2]),
|
||||
0, (float)(viewport[3]),
|
||||
(float)(0),
|
||||
(float)(100));
|
||||
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_cogl_current_matrix_push ();
|
||||
_cogl_current_matrix_identity ();
|
||||
|
||||
/* Direct copy operation */
|
||||
|
||||
if (ctx->drv.texture_download_material == COGL_INVALID_HANDLE)
|
||||
{
|
||||
ctx->drv.texture_download_material = cogl_material_new ();
|
||||
cogl_material_set_blend (ctx->drv.texture_download_material,
|
||||
"RGBA = ADD (SRC_COLOR, 0)",
|
||||
NULL);
|
||||
}
|
||||
|
||||
prev_source = cogl_handle_ref (ctx->source_material);
|
||||
cogl_set_source (ctx->drv.texture_download_material);
|
||||
|
||||
cogl_material_set_layer (ctx->drv.texture_download_material, 0, tex);
|
||||
|
||||
cogl_material_set_layer_combine (ctx->drv.texture_download_material,
|
||||
0, /* layer */
|
||||
"RGBA = REPLACE (TEXTURE)",
|
||||
NULL);
|
||||
|
||||
_cogl_texture_draw_and_read (tex, target_bmp, viewport);
|
||||
|
||||
/* Check whether texture has alpha and framebuffer not */
|
||||
/* FIXME: For some reason even if ALPHA_BITS is 8, the framebuffer
|
||||
still doesn't seem to have an alpha buffer. This might be just
|
||||
a PowerVR issue.
|
||||
GLint r_bits, g_bits, b_bits, a_bits;
|
||||
GE( glGetIntegerv (GL_ALPHA_BITS, &a_bits) );
|
||||
GE( glGetIntegerv (GL_RED_BITS, &r_bits) );
|
||||
GE( glGetIntegerv (GL_GREEN_BITS, &g_bits) );
|
||||
GE( glGetIntegerv (GL_BLUE_BITS, &b_bits) );
|
||||
printf ("R bits: %d\n", r_bits);
|
||||
printf ("G bits: %d\n", g_bits);
|
||||
printf ("B bits: %d\n", b_bits);
|
||||
printf ("A bits: %d\n", a_bits); */
|
||||
if ((tex->bitmap.format & COGL_A_BIT)/* && a_bits == 0*/)
|
||||
{
|
||||
guchar *srcdata;
|
||||
guchar *dstdata;
|
||||
guchar *srcpixel;
|
||||
guchar *dstpixel;
|
||||
gint x,y;
|
||||
|
||||
/* Create temp bitmap for alpha values */
|
||||
alpha_bmp.format = COGL_PIXEL_FORMAT_RGBA_8888;
|
||||
alpha_bmp.width = target_bmp->width;
|
||||
alpha_bmp.height = target_bmp->height;
|
||||
alpha_bmp.rowstride = bpp * alpha_bmp.width;
|
||||
alpha_bmp.data = (guchar*) g_malloc (alpha_bmp.rowstride *
|
||||
alpha_bmp.height);
|
||||
|
||||
/* Draw alpha values into RGB channels */
|
||||
cogl_material_set_layer_combine (ctx->drv.texture_download_material,
|
||||
0, /* layer */
|
||||
"RGBA = REPLACE (TEXTURE[A])",
|
||||
NULL);
|
||||
|
||||
_cogl_texture_draw_and_read (tex, &alpha_bmp, viewport);
|
||||
|
||||
/* Copy temp R to target A */
|
||||
srcdata = alpha_bmp.data;
|
||||
dstdata = target_bmp->data;
|
||||
|
||||
for (y=0; y<target_bmp->height; ++y)
|
||||
{
|
||||
for (x=0; x<target_bmp->width; ++x)
|
||||
{
|
||||
srcpixel = srcdata + x*bpp;
|
||||
dstpixel = dstdata + x*bpp;
|
||||
dstpixel[3] = srcpixel[0];
|
||||
}
|
||||
srcdata += alpha_bmp.rowstride;
|
||||
dstdata += target_bmp->rowstride;
|
||||
}
|
||||
|
||||
g_free (alpha_bmp.data);
|
||||
}
|
||||
|
||||
/* Restore old state */
|
||||
_cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
|
||||
_cogl_current_matrix_pop ();
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_cogl_current_matrix_pop ();
|
||||
|
||||
/* restore the original material */
|
||||
cogl_set_source (prev_source);
|
||||
cogl_handle_unref (prev_source);
|
||||
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
Loading…
Reference in New Issue
Block a user