mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +00:00
Improve cogl-texture maintainability by moving 90% into cogl/common
This splits the limited components that differed between cogl/{gl,gles}/cogl-texture.c into new {gl,gles}/cogl-texture-driver.c files and the rest that can now be shared into cogl/common/cogl-texture.c
This commit is contained in:
parent
4f5e6b77d5
commit
739b460c7a
@ -84,6 +84,9 @@ libclutter_cogl_common_la_SOURCES = \
|
||||
cogl-blend-string.c \
|
||||
cogl-blend-string.h \
|
||||
cogl-debug.c \
|
||||
cogl-texture-private.h \
|
||||
cogl-texture-driver.h \
|
||||
cogl-texture.c \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST = stb_image.c cogl-enum-types.h.in cogl-enum-types.c.in
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define __COGL_INTERNAL_H
|
||||
|
||||
#include "cogl-debug.h"
|
||||
#include "cogl-types.h"
|
||||
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
typedef enum {
|
||||
|
157
common/cogl-texture-driver.h
Normal file
157
common/cogl-texture-driver.h
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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_DRIVER_H
|
||||
#define __COGL_TEXTURE_DRIVER_H
|
||||
|
||||
/*
|
||||
* Basically just a wrapper around glBindTexture, but the GLES2 backend
|
||||
* for example also wants to know about the internal format so it can
|
||||
* identify when alpha only textures are bound.
|
||||
*/
|
||||
void
|
||||
_cogl_texture_driver_bind (GLenum gl_target, GLuint gl_handle, GLenum gl_intformat);
|
||||
|
||||
/*
|
||||
* This sets up the glPixelStore state for an upload to a destination with
|
||||
* the same size, and with no offset.
|
||||
*/
|
||||
/* NB: GLES can't upload a sub region of pixel data from a larger source
|
||||
* buffer which is why this interface is limited. The GL driver has a more
|
||||
* flexible version of this function that is uses internally */
|
||||
void
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride,
|
||||
int pixels_bpp);
|
||||
|
||||
/*
|
||||
* This uploads a sub-region from source_bmp to a single GL texture handle (i.e
|
||||
* a single CoglTexture slice)
|
||||
*
|
||||
* It also updates the array of tex->first_pixels[slice_index] if
|
||||
* dst_{x,y} == 0
|
||||
*
|
||||
* The driver abstraction is in place because GLES doesn't support the pixel
|
||||
* store options required to source from a subregion, so for GLES we have
|
||||
* to manually create a transient source bitmap.
|
||||
*
|
||||
* XXX: sorry for the ridiculous number of arguments :-(
|
||||
*/
|
||||
void
|
||||
_cogl_texture_driver_upload_subregion_to_gl (CoglTexture *tex,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height,
|
||||
CoglBitmap *source_bmp,
|
||||
GLuint source_gl_format,
|
||||
GLuint source_gl_type,
|
||||
GLuint gl_handle);
|
||||
|
||||
/*
|
||||
* This sets up the glPixelStore state for an download to a destination with
|
||||
* the same size, and with no offset.
|
||||
*/
|
||||
/* NB: GLES can't download pixel data into a sub region of a larger destination
|
||||
* buffer, the GL driver has a more flexible version of this function that it
|
||||
* uses internally. */
|
||||
void
|
||||
_cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride,
|
||||
int pixels_bpp);
|
||||
|
||||
/*
|
||||
* This driver abstraction is in place because GLES doesn't have a sane way to
|
||||
* download data from a texture so you litterally render the texture to the
|
||||
* backbuffer, and retrive the data using glReadPixels :-(
|
||||
*/
|
||||
gboolean
|
||||
_cogl_texture_driver_download_from_gl (CoglTexture *tex,
|
||||
CoglBitmap *target_bmp,
|
||||
GLuint target_gl_format,
|
||||
GLuint target_gl_type);
|
||||
|
||||
/*
|
||||
* It may depend on the driver as to what texture sizes are supported...
|
||||
*/
|
||||
gboolean
|
||||
_cogl_texture_driver_size_supported (GLenum gl_target,
|
||||
GLenum gl_format,
|
||||
GLenum gl_type,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
/*
|
||||
* This driver abstraction is needed because GLES doesn't support setting
|
||||
* a texture border color.
|
||||
*/
|
||||
void
|
||||
_cogl_texture_driver_try_setting_gl_border_color (
|
||||
GLuint gl_target,
|
||||
const GLfloat *transparent_color);
|
||||
|
||||
/*
|
||||
* XXX: this should live in cogl/{gl,gles}/cogl.c
|
||||
*/
|
||||
gboolean
|
||||
_cogl_pixel_format_from_gl_internal (GLenum gl_int_format,
|
||||
CoglPixelFormat *out_format);
|
||||
|
||||
/*
|
||||
* XXX: this should live in cogl/{gl,gles}/cogl.c
|
||||
*/
|
||||
CoglPixelFormat
|
||||
_cogl_pixel_format_to_gl (CoglPixelFormat format,
|
||||
GLenum *out_glintformat,
|
||||
GLenum *out_glformat,
|
||||
GLenum *out_gltype);
|
||||
|
||||
/*
|
||||
* It may depend on the driver as to what texture targets may be used when
|
||||
* creating a foreign texture. E.g. OpenGL supports ARB_texture_rectangle
|
||||
* but GLES doesn't
|
||||
*/
|
||||
gboolean
|
||||
_cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target);
|
||||
|
||||
/*
|
||||
* glGenerateMipmap semantics may need to be emulated for some drivers. E.g. by
|
||||
* enabling auto mipmap generation an re-loading a number of known texels.
|
||||
*/
|
||||
void
|
||||
_cogl_texture_driver_gl_generate_mipmaps (GLenum texture_target);
|
||||
|
||||
/*
|
||||
* The driver may impose constraints on what formats can be used to store
|
||||
* texture data read from textures. For example GLES currently only supports
|
||||
* RGBA_8888, and so we need to manually convert the data if the final
|
||||
* destination has another format.
|
||||
*/
|
||||
CoglPixelFormat
|
||||
_cogl_texture_driver_find_best_gl_get_data_format (
|
||||
CoglPixelFormat format,
|
||||
GLenum *closest_gl_format,
|
||||
GLenum *closest_gl_type);
|
||||
|
||||
#endif /* __COGL_TEXTURE_DRIVER_H */
|
||||
|
@ -21,8 +21,8 @@
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __COGL_TEXTURE_H
|
||||
#define __COGL_TEXTURE_H
|
||||
#ifndef __COGL_TEXTURE_PRIVATE_H
|
||||
#define __COGL_TEXTURE_PRIVATE_H
|
||||
|
||||
#include "cogl-bitmap-private.h"
|
||||
#include "cogl-handle.h"
|
||||
@ -142,4 +142,10 @@ _cogl_span_iter_end (CoglSpanIter *iter);
|
||||
void
|
||||
_cogl_span_iter_next (CoglSpanIter *iter);
|
||||
|
||||
#endif /* __COGL_TEXTURE_H */
|
||||
void
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_upload (int pixels_rowstride);
|
||||
|
||||
void
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_download (int pixels_rowstride);
|
||||
|
||||
#endif /* __COGL_TEXTURE_PRIVATE_H */
|
@ -36,6 +36,7 @@
|
||||
#include "cogl-bitmap.h"
|
||||
#include "cogl-bitmap-private.h"
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-texture-driver.h"
|
||||
#include "cogl-material.h"
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-handle.h"
|
||||
@ -45,22 +46,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
|
||||
#define glDrawRangeElements ctx->pf_glDrawRangeElements
|
||||
#define glActiveTexture ctx->pf_glActiveTexture
|
||||
#define glClientActiveTexture ctx->pf_glClientActiveTexture
|
||||
#define glGenerateMipmap ctx->pf_glGenerateMipmapEXT
|
||||
|
||||
#else
|
||||
|
||||
/* GLES doesn't have glDrawRangeElements, so we simply pretend it does
|
||||
* but that it makes no use of the start, end constraints: */
|
||||
#define glDrawRangeElements(mode, start, end, count, type, indices) \
|
||||
glDrawElements (mode, count, type, indices)
|
||||
|
||||
#endif
|
||||
|
||||
static void _cogl_texture_free (CoglTexture *tex);
|
||||
|
||||
COGL_HANDLE_DEFINE (Texture, texture);
|
||||
@ -162,17 +147,9 @@ _cogl_span_iter_end (CoglSpanIter *iter)
|
||||
return iter->pos >= iter->cover_end;
|
||||
}
|
||||
|
||||
static void
|
||||
prep_for_gl_pixels_upload (gint pixels_rowstride,
|
||||
gint pixels_src_x,
|
||||
gint pixels_src_y,
|
||||
gint pixels_bpp)
|
||||
void
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_upload (int pixels_rowstride)
|
||||
{
|
||||
GE( glPixelStorei (GL_UNPACK_ROW_LENGTH, pixels_rowstride / pixels_bpp) );
|
||||
|
||||
GE( glPixelStorei (GL_UNPACK_SKIP_PIXELS, pixels_src_x) );
|
||||
GE( glPixelStorei (GL_UNPACK_SKIP_ROWS, pixels_src_y) );
|
||||
|
||||
if (!(pixels_rowstride & 0x7))
|
||||
GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 8) );
|
||||
else if (!(pixels_rowstride & 0x3))
|
||||
@ -183,17 +160,9 @@ prep_for_gl_pixels_upload (gint pixels_rowstride,
|
||||
GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 1) );
|
||||
}
|
||||
|
||||
static void
|
||||
prep_for_gl_pixels_download (gint pixels_rowstride,
|
||||
gint pixels_src_x,
|
||||
gint pixels_src_y,
|
||||
gint pixels_bpp)
|
||||
void
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_download (int pixels_rowstride)
|
||||
{
|
||||
GE( glPixelStorei (GL_PACK_ROW_LENGTH, pixels_rowstride / pixels_bpp) );
|
||||
|
||||
GE( glPixelStorei (GL_PACK_SKIP_PIXELS, pixels_src_x) );
|
||||
GE( glPixelStorei (GL_PACK_SKIP_ROWS, pixels_src_y) );
|
||||
|
||||
if (!(pixels_rowstride & 0x7))
|
||||
GE( glPixelStorei (GL_PACK_ALIGNMENT, 8) );
|
||||
else if (!(pixels_rowstride & 0x3))
|
||||
@ -262,11 +231,18 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
/* Pick the gl texture object handle */
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num);
|
||||
|
||||
/* Setup gl alignment to match rowstride and top-left corner */
|
||||
prep_for_gl_pixels_upload (tex->bitmap.rowstride,
|
||||
x_span->start,
|
||||
y_span->start,
|
||||
bpp);
|
||||
_cogl_texture_driver_upload_subregion_to_gl (
|
||||
tex,
|
||||
x_span->start, /* src x */
|
||||
y_span->start, /* src y */
|
||||
0, /* dst x */
|
||||
0, /* dst y */
|
||||
x_span->size - x_span->waste, /* width */
|
||||
y_span->size - y_span->waste, /* height */
|
||||
&tex->bitmap,
|
||||
tex->gl_format,
|
||||
tex->gl_type,
|
||||
gl_handle);
|
||||
|
||||
/* Keep a copy of the first pixel if needed */
|
||||
if (tex->first_pixels)
|
||||
@ -279,17 +255,6 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
tex->first_pixels[slice_num].gl_type = tex->gl_type;
|
||||
}
|
||||
|
||||
/* Upload new image data */
|
||||
GE( glBindTexture (tex->gl_target, gl_handle) );
|
||||
|
||||
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||
0,
|
||||
0,
|
||||
x_span->size - x_span->waste,
|
||||
y_span->size - y_span->waste,
|
||||
tex->gl_format, tex->gl_type,
|
||||
tex->bitmap.data) );
|
||||
|
||||
/* Fill the waste with a copies of the rightmost pixels */
|
||||
if (x_span->waste > 0)
|
||||
{
|
||||
@ -309,9 +274,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
src += tex->bitmap.rowstride;
|
||||
}
|
||||
|
||||
prep_for_gl_pixels_upload (x_span->waste * bpp,
|
||||
0, /* src x */
|
||||
0, /* src y */
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
||||
x_span->waste * bpp,
|
||||
bpp);
|
||||
|
||||
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||
@ -344,9 +308,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
}
|
||||
}
|
||||
|
||||
prep_for_gl_pixels_upload (x_span->size * bpp,
|
||||
0, /* src x */
|
||||
0, /* src y */
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
||||
x_span->size * bpp,
|
||||
bpp);
|
||||
|
||||
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||
@ -368,95 +331,6 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_download_from_gl (CoglTexture *tex,
|
||||
CoglBitmap *target_bmp,
|
||||
GLuint target_gl_format,
|
||||
GLuint target_gl_type)
|
||||
{
|
||||
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 */
|
||||
prep_for_gl_pixels_download (slice_bmp.rowstride, 0, 0, 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;
|
||||
|
||||
prep_for_gl_pixels_download (target_bmp->rowstride, 0, 0, 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) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
gint src_x,
|
||||
@ -529,27 +403,29 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
x_iter.index);
|
||||
|
||||
/* Pick intersection width and height */
|
||||
inter_w = (x_iter.intersect_end -
|
||||
x_iter.intersect_start);
|
||||
inter_h = (y_iter.intersect_end -
|
||||
y_iter.intersect_start);
|
||||
inter_w = (x_iter.intersect_end - x_iter.intersect_start);
|
||||
inter_h = (y_iter.intersect_end - y_iter.intersect_start);
|
||||
|
||||
/* Localize intersection top-left corner to slice*/
|
||||
local_x = (x_iter.intersect_start -
|
||||
x_iter.pos);
|
||||
local_y = (y_iter.intersect_start -
|
||||
y_iter.pos);
|
||||
local_x = (x_iter.intersect_start - x_iter.pos);
|
||||
local_y = (y_iter.intersect_start - y_iter.pos);
|
||||
|
||||
slice_num = y_iter.index * tex->slice_x_spans->len + x_iter.index;
|
||||
|
||||
/* Pick slice GL handle */
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num);
|
||||
|
||||
/* Setup gl alignment to match rowstride and top-left corner */
|
||||
prep_for_gl_pixels_upload (source_bmp->rowstride,
|
||||
_cogl_texture_driver_upload_subregion_to_gl (tex,
|
||||
source_x,
|
||||
source_y,
|
||||
bpp);
|
||||
local_x, /* dst x */
|
||||
local_y, /* dst x */
|
||||
inter_w, /* width */
|
||||
inter_h, /* height */
|
||||
source_bmp,
|
||||
source_gl_format,
|
||||
source_gl_type,
|
||||
gl_handle);
|
||||
|
||||
/* Keep a copy of the first pixel if needed */
|
||||
if (tex->first_pixels && local_x == 0 && local_y == 0)
|
||||
@ -562,16 +438,6 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
tex->first_pixels[slice_num].gl_type = source_gl_type;
|
||||
}
|
||||
|
||||
/* Upload new image data */
|
||||
GE( glBindTexture (tex->gl_target, gl_handle) );
|
||||
|
||||
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||
local_x, local_y,
|
||||
inter_w, inter_h,
|
||||
source_gl_format,
|
||||
source_gl_type,
|
||||
source_bmp->data) );
|
||||
|
||||
/* If the x_span is sliced and the upload touches the
|
||||
rightmost pixels then fill the waste with copies of the
|
||||
pixels */
|
||||
@ -603,9 +469,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
src += source_bmp->rowstride;
|
||||
}
|
||||
|
||||
prep_for_gl_pixels_upload (x_span->waste * bpp,
|
||||
0, /* src x */
|
||||
0, /* src y */
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
||||
x_span->waste * bpp,
|
||||
bpp);
|
||||
|
||||
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||
@ -655,9 +520,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
}
|
||||
}
|
||||
|
||||
prep_for_gl_pixels_upload (copy_width * bpp,
|
||||
0, /* src x */
|
||||
0, /* src y */
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
||||
copy_width * bpp,
|
||||
bpp);
|
||||
|
||||
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||
@ -739,7 +603,9 @@ _cogl_pot_slices_for_size (gint size_to_fill,
|
||||
if (size_to_fill > span.size)
|
||||
{
|
||||
/* Not yet - add a span of this size */
|
||||
if (out_spans) g_array_append_val (out_spans, span);
|
||||
if (out_spans)
|
||||
g_array_append_val (out_spans, span);
|
||||
|
||||
span.start += span.size;
|
||||
size_to_fill -= span.size;
|
||||
n_spans++;
|
||||
@ -748,7 +614,9 @@ _cogl_pot_slices_for_size (gint size_to_fill,
|
||||
{
|
||||
/* Yes and waste is small enough */
|
||||
span.waste = span.size - size_to_fill;
|
||||
if (out_spans) g_array_append_val (out_spans, span);
|
||||
if (out_spans)
|
||||
g_array_append_val (out_spans, span);
|
||||
|
||||
return ++n_spans;
|
||||
}
|
||||
else
|
||||
@ -766,35 +634,6 @@ _cogl_pot_slices_for_size (gint size_to_fill,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_size_supported (GLenum gl_target,
|
||||
GLenum gl_format,
|
||||
GLenum gl_type,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (gl_target == GL_TEXTURE_2D)
|
||||
{
|
||||
/* Proxy texture allows for a quick check for supported size */
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not used */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_set_wrap_mode_parameter (CoglTexture *tex,
|
||||
GLenum wrap_mode)
|
||||
@ -863,7 +702,7 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
CoglTexSliceSpan span;
|
||||
|
||||
/* Check if size supported else bail out */
|
||||
if (!_cogl_texture_size_supported (tex->gl_target,
|
||||
if (!_cogl_texture_driver_size_supported (tex->gl_target,
|
||||
tex->gl_format,
|
||||
tex->gl_type,
|
||||
max_width,
|
||||
@ -897,7 +736,7 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
else
|
||||
{
|
||||
/* Decrease the size of largest slice until supported by GL */
|
||||
while (!_cogl_texture_size_supported (tex->gl_target,
|
||||
while (!_cogl_texture_driver_size_supported (tex->gl_target,
|
||||
tex->gl_format,
|
||||
tex->gl_type,
|
||||
max_width,
|
||||
@ -951,7 +790,7 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
g_array_set_size (tex->slice_gl_handles, n_slices);
|
||||
|
||||
/* Allocate some space to store a copy of the first pixel of each
|
||||
slice. This is only needed to glGenerateMipmap (which is part of
|
||||
slice. This is only needed if glGenerateMipmap (which is part of
|
||||
the FBO extension) is not available */
|
||||
if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||
tex->first_pixels = NULL;
|
||||
@ -984,14 +823,12 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
y_span->size - y_span->waste);
|
||||
|
||||
/* Setup texture parameters */
|
||||
GE( glBindTexture (tex->gl_target,
|
||||
gl_handles[y * n_x_slices + x]) );
|
||||
GE( _cogl_texture_driver_bind (tex->gl_target,
|
||||
gl_handles[y * n_x_slices + x],
|
||||
tex->gl_intformat) );
|
||||
|
||||
/* Use a transparent border color so that we can leave the
|
||||
color buffer alone when using texture co-ordinates
|
||||
outside of the texture */
|
||||
GE( glTexParameterfv (tex->gl_target, GL_TEXTURE_BORDER_COLOR,
|
||||
transparent_color) );
|
||||
_cogl_texture_driver_try_setting_gl_border_color (tex->gl_target,
|
||||
transparent_color);
|
||||
|
||||
/* Pass NULL data to init size and internal format */
|
||||
GE( glTexImage2D (tex->gl_target, 0, tex->gl_intformat,
|
||||
@ -1041,153 +878,6 @@ _cogl_texture_span_has_waste (CoglTexture *tex,
|
||||
return (x_span->waste || y_span->waste) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_pixel_format_from_gl_internal (GLenum gl_int_format,
|
||||
CoglPixelFormat *out_format)
|
||||
{
|
||||
/* It doesn't really matter we convert to exact same
|
||||
format (some have no cogl match anyway) since format
|
||||
is re-matched against cogl when getting or setting
|
||||
texture image data.
|
||||
*/
|
||||
|
||||
switch (gl_int_format)
|
||||
{
|
||||
case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8:
|
||||
case GL_ALPHA12: case GL_ALPHA16:
|
||||
|
||||
*out_format = COGL_PIXEL_FORMAT_A_8;
|
||||
return TRUE;
|
||||
|
||||
case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8:
|
||||
case GL_LUMINANCE12: case GL_LUMINANCE16:
|
||||
|
||||
*out_format = COGL_PIXEL_FORMAT_G_8;
|
||||
return TRUE;
|
||||
|
||||
case GL_RGB: case GL_RGB4: case GL_RGB5: case GL_RGB8:
|
||||
case GL_RGB10: case GL_RGB12: case GL_RGB16: case GL_R3_G3_B2:
|
||||
|
||||
*out_format = COGL_PIXEL_FORMAT_RGB_888;
|
||||
return TRUE;
|
||||
|
||||
case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1:
|
||||
case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16:
|
||||
|
||||
*out_format = COGL_PIXEL_FORMAT_RGBA_8888;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static CoglPixelFormat
|
||||
_cogl_pixel_format_to_gl (CoglPixelFormat format,
|
||||
GLenum *out_glintformat,
|
||||
GLenum *out_glformat,
|
||||
GLenum *out_gltype)
|
||||
{
|
||||
CoglPixelFormat required_format;
|
||||
GLenum glintformat = 0;
|
||||
GLenum glformat = 0;
|
||||
GLenum gltype = 0;
|
||||
|
||||
/* FIXME: check YUV support */
|
||||
|
||||
required_format = format;
|
||||
|
||||
/* Find GL equivalents */
|
||||
switch (format & COGL_UNPREMULT_MASK)
|
||||
{
|
||||
case COGL_PIXEL_FORMAT_A_8:
|
||||
glintformat = GL_ALPHA;
|
||||
glformat = GL_ALPHA;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_G_8:
|
||||
glintformat = GL_LUMINANCE;
|
||||
glformat = GL_LUMINANCE;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case COGL_PIXEL_FORMAT_RGB_888:
|
||||
glintformat = GL_RGB;
|
||||
glformat = GL_RGB;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_BGR_888:
|
||||
glintformat = GL_RGB;
|
||||
glformat = GL_BGR;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_RGBA_8888:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_BGRA_8888:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_BGRA;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
/* The following two types of channel ordering
|
||||
* have no GL equivalent unless defined using
|
||||
* system word byte ordering */
|
||||
case COGL_PIXEL_FORMAT_ARGB_8888:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_BGRA;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
gltype = GL_UNSIGNED_INT_8_8_8_8;
|
||||
#else
|
||||
gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case COGL_PIXEL_FORMAT_ABGR_8888:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
gltype = GL_UNSIGNED_INT_8_8_8_8;
|
||||
#else
|
||||
gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* The following three types of channel ordering
|
||||
* are always defined using system word byte
|
||||
* ordering (even according to GLES spec) */
|
||||
case COGL_PIXEL_FORMAT_RGB_565:
|
||||
glintformat = GL_RGB;
|
||||
glformat = GL_RGB;
|
||||
gltype = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_RGBA_4444:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_RGBA_5551:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
break;
|
||||
|
||||
/* FIXME: check extensions for YUV support */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (out_glintformat != NULL)
|
||||
*out_glintformat = glintformat;
|
||||
if (out_glformat != NULL)
|
||||
*out_glformat = glformat;
|
||||
if (out_gltype != NULL)
|
||||
*out_gltype = gltype;
|
||||
|
||||
return required_format;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_bitmap_prepare (CoglTexture *tex,
|
||||
CoglPixelFormat internal_format)
|
||||
@ -1496,14 +1186,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
CoglTexSliceSpan x_span;
|
||||
CoglTexSliceSpan y_span;
|
||||
|
||||
/* GL_ARB_texture_rectangle textures are supported if they are
|
||||
created from foreign because some chipsets have trouble with
|
||||
GL_ARB_texture_non_power_of_two. There is no Cogl call to create
|
||||
them directly to emphasize the fact that they don't work fully
|
||||
(for example, no mipmapping and complicated shader support) */
|
||||
|
||||
/* Allow 2-dimensional or rectangle textures only */
|
||||
if (gl_target != GL_TEXTURE_2D && gl_target != CGL_TEXTURE_RECTANGLE_ARB)
|
||||
if (!_cogl_texture_driver_allows_foreign_gl_target (gl_target))
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
/* Make sure it is a valid GL texture object */
|
||||
@ -1520,6 +1203,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
/* Obtain texture parameters
|
||||
(only level 0 we are interested in) */
|
||||
|
||||
#if HAVE_COGL_GL
|
||||
GE( glGetTexLevelParameteriv (gl_target, 0,
|
||||
GL_TEXTURE_COMPRESSED,
|
||||
&gl_compressed) );
|
||||
@ -1536,6 +1220,10 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
GE( glGetTexLevelParameteriv (gl_target, 0,
|
||||
GL_TEXTURE_HEIGHT,
|
||||
&gl_height) );
|
||||
#else
|
||||
gl_width = width + x_pot_waste;
|
||||
gl_height = height + y_pot_waste;
|
||||
#endif
|
||||
|
||||
GE( glGetTexParameteriv (gl_target,
|
||||
GL_GENERATE_MIPMAP,
|
||||
@ -1796,7 +1484,7 @@ _cogl_texture_ensure_mipmaps (CoglHandle handle)
|
||||
|
||||
/* glGenerateMipmap is defined in the FBO extension */
|
||||
if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||
GE( glGenerateMipmap (tex->gl_target) );
|
||||
_cogl_texture_driver_gl_generate_mipmaps (tex->gl_target);
|
||||
else if (tex->first_pixels)
|
||||
{
|
||||
CoglTexturePixel *pixel = tex->first_pixels + i;
|
||||
@ -1935,12 +1623,10 @@ cogl_texture_get_data (CoglHandle handle,
|
||||
byte_size = tex->bitmap.height * rowstride;
|
||||
if (data == NULL) return byte_size;
|
||||
|
||||
/* Find closest format that's supported by GL */
|
||||
closest_format = _cogl_pixel_format_to_gl (format,
|
||||
NULL, /* don't need */
|
||||
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);
|
||||
|
||||
/* Is the requested format supported? */
|
||||
@ -1963,7 +1649,7 @@ cogl_texture_get_data (CoglHandle handle,
|
||||
}
|
||||
|
||||
/* Retrieve data from slices */
|
||||
_cogl_texture_download_from_gl (tex, &target_bmp,
|
||||
_cogl_texture_driver_download_from_gl (tex, &target_bmp,
|
||||
closest_gl_format,
|
||||
closest_gl_type);
|
||||
|
@ -20,7 +20,6 @@ cogl_headers = \
|
||||
$(NULL)
|
||||
|
||||
cogl_priv_headers = \
|
||||
cogl-texture-private.h \
|
||||
cogl-fbo.h \
|
||||
cogl-shader-private.h \
|
||||
cogl-program.h \
|
||||
@ -30,7 +29,7 @@ cogl_priv_headers = \
|
||||
cogl_sources = \
|
||||
cogl.c \
|
||||
cogl-primitives.c \
|
||||
cogl-texture.c \
|
||||
cogl-texture-driver.c \
|
||||
cogl-fbo.c \
|
||||
cogl-shader.c \
|
||||
cogl-program.c \
|
||||
|
454
gl/cogl-texture-driver.c
Normal file
454
gl/cogl-texture-driver.c
Normal file
@ -0,0 +1,454 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Authors:
|
||||
* Matthew Allum <mallum@openedhand.com>
|
||||
* Neil Roberts <neil@linux.intel.com>
|
||||
* Robert Bragg <robert@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "cogl.h"
|
||||
#include "cogl-internal.h"
|
||||
#include "cogl-util.h"
|
||||
#include "cogl-bitmap.h"
|
||||
#include "cogl-bitmap-private.h"
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-material.h"
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-primitives.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#define glGenerateMipmap ctx->pf_glGenerateMipmapEXT
|
||||
|
||||
void
|
||||
_cogl_texture_driver_bind (GLenum gl_target,
|
||||
GLuint gl_handle,
|
||||
GLenum gl_intformat)
|
||||
{
|
||||
GE (glBindTexture (gl_target, gl_handle));
|
||||
}
|
||||
|
||||
/* OpenGL - unlike GLES - can upload a sub region of pixel data from a larger
|
||||
* source buffer */
|
||||
static void
|
||||
prep_gl_for_pixels_upload_full (int pixels_rowstride,
|
||||
int pixels_src_x,
|
||||
int pixels_src_y,
|
||||
int pixels_bpp)
|
||||
{
|
||||
GE( glPixelStorei (GL_UNPACK_ROW_LENGTH, pixels_rowstride / pixels_bpp) );
|
||||
|
||||
GE( glPixelStorei (GL_UNPACK_SKIP_PIXELS, pixels_src_x) );
|
||||
GE( glPixelStorei (GL_UNPACK_SKIP_ROWS, pixels_src_y) );
|
||||
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_upload (pixels_rowstride);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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 pixels_src_x,
|
||||
int pixels_src_y,
|
||||
int pixels_bpp)
|
||||
{
|
||||
GE( glPixelStorei (GL_PACK_ROW_LENGTH, pixels_rowstride / pixels_bpp) );
|
||||
|
||||
GE( glPixelStorei (GL_PACK_SKIP_PIXELS, pixels_src_x) );
|
||||
GE( glPixelStorei (GL_PACK_SKIP_ROWS, pixels_src_y) );
|
||||
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_download (pixels_rowstride);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_driver_upload_subregion_to_gl (CoglTexture *tex,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height,
|
||||
CoglBitmap *source_bmp,
|
||||
GLuint source_gl_format,
|
||||
GLuint source_gl_type,
|
||||
GLuint gl_handle)
|
||||
{
|
||||
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,
|
||||
src_x,
|
||||
src_y,
|
||||
bpp);
|
||||
|
||||
/* Upload new image data */
|
||||
GE( _cogl_texture_driver_bind (tex->gl_target,
|
||||
gl_handle, tex->gl_intformat) );
|
||||
|
||||
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||
dst_x, dst_y,
|
||||
width, height,
|
||||
source_gl_format,
|
||||
source_gl_type,
|
||||
source_bmp->data) );
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_download_from_gl (CoglTexture *tex,
|
||||
CoglBitmap *target_bmp,
|
||||
GLuint target_gl_format,
|
||||
GLuint target_gl_type)
|
||||
{
|
||||
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) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_size_supported (GLenum gl_target,
|
||||
GLenum gl_format,
|
||||
GLenum gl_type,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (gl_target == GL_TEXTURE_2D)
|
||||
{
|
||||
/* Proxy texture allows for a quick check for supported size */
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not used */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_driver_try_setting_gl_border_color (
|
||||
GLuint gl_target,
|
||||
const GLfloat *transparent_color)
|
||||
{
|
||||
/* Use a transparent border color so that we can leave the
|
||||
color buffer alone when using texture co-ordinates
|
||||
outside of the texture */
|
||||
GE( glTexParameterfv (gl_target, GL_TEXTURE_BORDER_COLOR,
|
||||
transparent_color) );
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_pixel_format_from_gl_internal (GLenum gl_int_format,
|
||||
CoglPixelFormat *out_format)
|
||||
{
|
||||
/* It doesn't really matter we convert to exact same
|
||||
format (some have no cogl match anyway) since format
|
||||
is re-matched against cogl when getting or setting
|
||||
texture image data.
|
||||
*/
|
||||
|
||||
switch (gl_int_format)
|
||||
{
|
||||
case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8:
|
||||
case GL_ALPHA12: case GL_ALPHA16:
|
||||
|
||||
*out_format = COGL_PIXEL_FORMAT_A_8;
|
||||
return TRUE;
|
||||
|
||||
case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8:
|
||||
case GL_LUMINANCE12: case GL_LUMINANCE16:
|
||||
|
||||
*out_format = COGL_PIXEL_FORMAT_G_8;
|
||||
return TRUE;
|
||||
|
||||
case GL_RGB: case GL_RGB4: case GL_RGB5: case GL_RGB8:
|
||||
case GL_RGB10: case GL_RGB12: case GL_RGB16: case GL_R3_G3_B2:
|
||||
|
||||
*out_format = COGL_PIXEL_FORMAT_RGB_888;
|
||||
return TRUE;
|
||||
|
||||
case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1:
|
||||
case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16:
|
||||
|
||||
*out_format = COGL_PIXEL_FORMAT_RGBA_8888;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CoglPixelFormat
|
||||
_cogl_pixel_format_to_gl (CoglPixelFormat format,
|
||||
GLenum *out_glintformat,
|
||||
GLenum *out_glformat,
|
||||
GLenum *out_gltype)
|
||||
{
|
||||
CoglPixelFormat required_format;
|
||||
GLenum glintformat = 0;
|
||||
GLenum glformat = 0;
|
||||
GLenum gltype = 0;
|
||||
|
||||
/* FIXME: check YUV support */
|
||||
|
||||
required_format = format;
|
||||
|
||||
/* Find GL equivalents */
|
||||
switch (format & COGL_UNPREMULT_MASK)
|
||||
{
|
||||
case COGL_PIXEL_FORMAT_A_8:
|
||||
glintformat = GL_ALPHA;
|
||||
glformat = GL_ALPHA;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_G_8:
|
||||
glintformat = GL_LUMINANCE;
|
||||
glformat = GL_LUMINANCE;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case COGL_PIXEL_FORMAT_RGB_888:
|
||||
glintformat = GL_RGB;
|
||||
glformat = GL_RGB;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_BGR_888:
|
||||
glintformat = GL_RGB;
|
||||
glformat = GL_BGR;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_RGBA_8888:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_BGRA_8888:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_BGRA;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
/* The following two types of channel ordering
|
||||
* have no GL equivalent unless defined using
|
||||
* system word byte ordering */
|
||||
case COGL_PIXEL_FORMAT_ARGB_8888:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_BGRA;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
gltype = GL_UNSIGNED_INT_8_8_8_8;
|
||||
#else
|
||||
gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case COGL_PIXEL_FORMAT_ABGR_8888:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
gltype = GL_UNSIGNED_INT_8_8_8_8;
|
||||
#else
|
||||
gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* The following three types of channel ordering
|
||||
* are always defined using system word byte
|
||||
* ordering (even according to GLES spec) */
|
||||
case COGL_PIXEL_FORMAT_RGB_565:
|
||||
glintformat = GL_RGB;
|
||||
glformat = GL_RGB;
|
||||
gltype = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_RGBA_4444:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_RGBA_5551:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
break;
|
||||
|
||||
/* FIXME: check extensions for YUV support */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (out_glintformat != NULL)
|
||||
*out_glintformat = glintformat;
|
||||
if (out_glformat != NULL)
|
||||
*out_glformat = glformat;
|
||||
if (out_gltype != NULL)
|
||||
*out_gltype = gltype;
|
||||
|
||||
return required_format;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target)
|
||||
{
|
||||
/* GL_ARB_texture_rectangle textures are supported if they are
|
||||
created from foreign because some chipsets have trouble with
|
||||
GL_ARB_texture_non_power_of_two. There is no Cogl call to create
|
||||
them directly to emphasize the fact that they don't work fully
|
||||
(for example, no mipmapping and complicated shader support) */
|
||||
|
||||
/* Allow 2-dimensional or rectangle textures only */
|
||||
if (gl_target != GL_TEXTURE_2D && gl_target != CGL_TEXTURE_RECTANGLE_ARB)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
GE( glGenerateMipmap (gl_target) );
|
||||
}
|
||||
|
||||
CoglPixelFormat
|
||||
_cogl_texture_driver_find_best_gl_get_data_format (
|
||||
CoglPixelFormat format,
|
||||
GLenum *closest_gl_format,
|
||||
GLenum *closest_gl_type)
|
||||
{
|
||||
/* Find closest format that's supported by GL */
|
||||
return _cogl_pixel_format_to_gl (format,
|
||||
NULL, /* don't need */
|
||||
closest_gl_format,
|
||||
closest_gl_type);
|
||||
}
|
||||
|
@ -48,12 +48,11 @@ libclutter_cogl_gles_la_SOURCES = \
|
||||
$(top_builddir)/clutter/cogl/cogl-texture.h \
|
||||
$(top_builddir)/clutter/cogl/cogl-types.h \
|
||||
$(top_builddir)/clutter/cogl/cogl-debug.h \
|
||||
cogl-texture-private.h \
|
||||
cogl-fbo.h \
|
||||
cogl-context.h \
|
||||
cogl.c \
|
||||
cogl-primitives.c \
|
||||
cogl-texture.c \
|
||||
cogl-texture-driver.c \
|
||||
cogl-fbo.c \
|
||||
cogl-context.c \
|
||||
cogl-gles2-wrapper.h \
|
||||
|
@ -24,6 +24,7 @@
|
||||
#ifndef __COGL_GLES2_WRAPPER_H__
|
||||
#define __COGL_GLES2_WRAPPER_H__
|
||||
|
||||
#include "cogl.h" /* needed for gl header include */
|
||||
#include "cogl-internal.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
481
gles/cogl-texture-driver.c
Normal file
481
gles/cogl-texture-driver.c
Normal file
@ -0,0 +1,481 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Authors:
|
||||
* Matthew Allum <mallum@openedhand.com>
|
||||
* Neil Roberts <neil@linux.intel.com>
|
||||
* Robert Bragg <robert@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "cogl.h"
|
||||
#include "cogl-internal.h"
|
||||
#include "cogl-util.h"
|
||||
#include "cogl-bitmap.h"
|
||||
#include "cogl-bitmap-private.h"
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-material.h"
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-primitives.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "cogl-gles2-wrapper.h"
|
||||
|
||||
|
||||
void
|
||||
_cogl_texture_driver_bind (GLenum gl_target,
|
||||
GLuint gl_handle,
|
||||
GLenum gl_intformat)
|
||||
{
|
||||
GE (cogl_gles2_wrapper_bind_texture (gl_target, gl_handle, gl_intformat));
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride,
|
||||
int pixels_bpp)
|
||||
{
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_upload (pixels_rowstride);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride,
|
||||
int pixels_bpp)
|
||||
{
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_download (pixels_rowstride);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_driver_upload_subregion_to_gl (CoglTexture *tex,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height,
|
||||
CoglBitmap *source_bmp,
|
||||
GLuint source_gl_format,
|
||||
GLuint source_gl_type,
|
||||
GLuint gl_handle)
|
||||
{
|
||||
int bpp = _cogl_get_format_bpp (source_bmp->format);
|
||||
CoglBitmap slice_bmp;
|
||||
|
||||
/* NB: GLES doesn't support the GL_UNPACK_ROW_LENGTH, GL_UNPACK_SKIP_PIXELS
|
||||
* or GL_UNPACK_SKIP_ROWS pixel store options so we can't directly source a
|
||||
* sub-region from source_bmp, we need to use a transient bitmap instead. */
|
||||
|
||||
/* FIXME: optimize by not copying to intermediate slice bitmap when source
|
||||
* rowstride = bpp * width and the texture image is not sliced */
|
||||
|
||||
/* Setup temp bitmap for slice subregion */
|
||||
slice_bmp.format = tex->bitmap.format;
|
||||
slice_bmp.width = width;
|
||||
slice_bmp.height = height;
|
||||
slice_bmp.rowstride = bpp * slice_bmp.width;
|
||||
slice_bmp.data = (guchar*) g_malloc (slice_bmp.rowstride * slice_bmp.height);
|
||||
|
||||
/* Setup gl alignment to match rowstride and top-left corner */
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (slice_bmp.rowstride,
|
||||
bpp);
|
||||
|
||||
/* Copy subregion data */
|
||||
_cogl_bitmap_copy_subregion (source_bmp,
|
||||
&slice_bmp,
|
||||
src_x,
|
||||
src_y,
|
||||
0, 0,
|
||||
slice_bmp.width,
|
||||
slice_bmp.height);
|
||||
|
||||
/* Upload new image data */
|
||||
GE( _cogl_texture_driver_bind (tex->gl_target,
|
||||
gl_handle, tex->gl_intformat) );
|
||||
|
||||
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||
dst_x, dst_y,
|
||||
width, height,
|
||||
source_gl_format,
|
||||
source_gl_type,
|
||||
slice_bmp.data) );
|
||||
|
||||
/* Free temp bitmap */
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_download_from_gl (CoglTexture *tex,
|
||||
CoglBitmap *target_bmp,
|
||||
GLuint target_gl_format,
|
||||
GLuint target_gl_type)
|
||||
{
|
||||
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->texture_download_material == COGL_INVALID_HANDLE)
|
||||
{
|
||||
ctx->texture_download_material = cogl_material_new ();
|
||||
cogl_material_set_blend (ctx->texture_download_material,
|
||||
"RGBA = ADD (SRC_COLOR, 0)",
|
||||
NULL);
|
||||
}
|
||||
|
||||
prev_source = cogl_handle_ref (ctx->source_material);
|
||||
cogl_set_source (ctx->texture_download_material);
|
||||
|
||||
cogl_material_set_layer (ctx->texture_download_material, 0, tex);
|
||||
|
||||
cogl_material_set_layer_combine (ctx->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->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;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_size_supported (GLenum gl_target,
|
||||
GLenum gl_format,
|
||||
GLenum gl_type,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_driver_try_setting_gl_border_color (
|
||||
GLuint gl_target,
|
||||
const GLfloat *transparent_color)
|
||||
{
|
||||
/* FAIL! */
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_pixel_format_from_gl_internal (GLenum gl_int_format,
|
||||
CoglPixelFormat *out_format)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CoglPixelFormat
|
||||
_cogl_pixel_format_to_gl (CoglPixelFormat format,
|
||||
GLenum *out_glintformat,
|
||||
GLenum *out_glformat,
|
||||
GLenum *out_gltype)
|
||||
{
|
||||
CoglPixelFormat required_format;
|
||||
GLenum glintformat = 0;
|
||||
GLenum glformat = 0;
|
||||
GLenum gltype = 0;
|
||||
|
||||
/* FIXME: check YUV support */
|
||||
|
||||
required_format = format;
|
||||
|
||||
/* Find GL equivalents */
|
||||
switch (format & COGL_UNPREMULT_MASK)
|
||||
{
|
||||
case COGL_PIXEL_FORMAT_A_8:
|
||||
glintformat = GL_ALPHA;
|
||||
glformat = GL_ALPHA;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_G_8:
|
||||
glintformat = GL_LUMINANCE;
|
||||
glformat = GL_LUMINANCE;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
/* Just one 24-bit ordering supported */
|
||||
case COGL_PIXEL_FORMAT_RGB_888:
|
||||
case COGL_PIXEL_FORMAT_BGR_888:
|
||||
glintformat = GL_RGB;
|
||||
glformat = GL_RGB;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
required_format = COGL_PIXEL_FORMAT_RGB_888;
|
||||
break;
|
||||
|
||||
/* Just one 32-bit ordering supported */
|
||||
case COGL_PIXEL_FORMAT_RGBA_8888:
|
||||
case COGL_PIXEL_FORMAT_BGRA_8888:
|
||||
case COGL_PIXEL_FORMAT_ARGB_8888:
|
||||
case COGL_PIXEL_FORMAT_ABGR_8888:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
required_format = COGL_PIXEL_FORMAT_RGBA_8888;
|
||||
required_format |= (format & COGL_PREMULT_BIT);
|
||||
break;
|
||||
|
||||
/* The following three types of channel ordering
|
||||
* are always defined using system word byte
|
||||
* ordering (even according to GLES spec) */
|
||||
case COGL_PIXEL_FORMAT_RGB_565:
|
||||
glintformat = GL_RGB;
|
||||
glformat = GL_RGB;
|
||||
gltype = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_RGBA_4444:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
break;
|
||||
case COGL_PIXEL_FORMAT_RGBA_5551:
|
||||
glintformat = GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
break;
|
||||
|
||||
/* FIXME: check extensions for YUV support */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (out_glintformat != NULL)
|
||||
*out_glintformat = glintformat;
|
||||
if (out_glformat != NULL)
|
||||
*out_glformat = glformat;
|
||||
if (out_gltype != NULL)
|
||||
*out_gltype = gltype;
|
||||
|
||||
return required_format;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target)
|
||||
{
|
||||
/* Allow 2-dimensional textures only */
|
||||
if (gl_target != GL_TEXTURE_2D)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target)
|
||||
{
|
||||
GE( cogl_wrap_glGenerateMipmap (gl_target) );
|
||||
}
|
||||
|
||||
CoglPixelFormat
|
||||
_cogl_texture_driver_find_best_gl_get_data_format (
|
||||
CoglPixelFormat format,
|
||||
GLenum *closest_gl_format,
|
||||
GLenum *closest_gl_type)
|
||||
{
|
||||
/* Find closest format that's supported by GL
|
||||
(Can't use _cogl_pixel_format_to_gl since available formats
|
||||
when reading pixels on GLES are severely limited) */
|
||||
*closest_gl_format = GL_RGBA;
|
||||
*closest_gl_type = GL_UNSIGNED_BYTE;
|
||||
return COGL_PIXEL_FORMAT_RGBA_8888;
|
||||
}
|
||||
|
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* 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_H
|
||||
#define __COGL_TEXTURE_H
|
||||
|
||||
#include "cogl-bitmap-private.h"
|
||||
#include "cogl-material-private.h"
|
||||
#include "cogl-handle.h"
|
||||
|
||||
typedef struct _CoglTexture CoglTexture;
|
||||
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
|
||||
typedef struct _CoglSpanIter CoglSpanIter;
|
||||
typedef struct _CoglTexturePixel CoglTexturePixel;
|
||||
|
||||
struct _CoglTexSliceSpan
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
/* 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 _CoglTexture
|
||||
{
|
||||
CoglHandleObject _parent;
|
||||
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
|
||||
* log the texture rectangles we want to draw to a journal, so when we
|
||||
* later flush the journal we aim to batch data, and gl draw calls. */
|
||||
typedef struct _CoglJournalEntry
|
||||
{
|
||||
CoglHandle material;
|
||||
gint n_layers;
|
||||
guint32 fallback_mask;
|
||||
GLuint layer0_override_texture;
|
||||
CoglMatrix model_view;
|
||||
CoglMaterialFlushOptions flush_options;
|
||||
} CoglJournalEntry;
|
||||
|
||||
CoglTexture*
|
||||
_cogl_texture_pointer_from_handle (CoglHandle handle);
|
||||
|
||||
void
|
||||
_cogl_texture_set_wrap_mode_parameter (CoglTexture *tex,
|
||||
GLenum wrap_mode);
|
||||
|
||||
void
|
||||
_cogl_texture_set_filters (CoglHandle handle,
|
||||
GLenum min_filter,
|
||||
GLenum mag_filter);
|
||||
|
||||
void
|
||||
_cogl_texture_ensure_mipmaps (CoglHandle handle);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_span_has_waste (CoglTexture *tex,
|
||||
gint x_span_index,
|
||||
gint y_span_index);
|
||||
|
||||
void
|
||||
_cogl_span_iter_begin (CoglSpanIter *iter,
|
||||
GArray *array,
|
||||
float origin,
|
||||
float cover_start,
|
||||
float cover_end);
|
||||
|
||||
gboolean
|
||||
_cogl_span_iter_end (CoglSpanIter *iter);
|
||||
|
||||
void
|
||||
_cogl_span_iter_next (CoglSpanIter *iter);
|
||||
|
||||
#endif /* __COGL_TEXTURE_H */
|
2066
gles/cogl-texture.c
2066
gles/cogl-texture.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user