[Cogl] [PATCH] texture: expose mipmap level in set region apis
Robert Bragg
robert at sixbynine.org
Mon Nov 26 15:47:03 PST 2012
From: Robert Bragg <robert at linux.intel.com>
cogl_texture_set_region() and cogl_texture_set_region_from_bitmap() now
have a level argument so image data can be uploaded to a specific mipmap
level.
The prototype for cogl_texture_set_region was also updated to simplify
the arguments.
The arguments for cogl_texture_set_region_from_bitmap were reordered to
be consistent with cogl_texture_set_region with the source related
arguments listed first followed by the destination arguments.
---
cogl-pango/cogl-pango-render.c | 13 +--
cogl/cogl-atlas-texture.c | 32 ++++--
cogl/cogl-blit.c | 17 ++--
cogl/cogl-driver.h | 16 ++--
cogl/cogl-pipeline-layer-state.c | 3 +
cogl/cogl-pipeline-layer-state.h | 5 +
cogl/cogl-sub-texture.c | 19 ++++-
cogl/cogl-texture-2d-private.h | 18 ++--
cogl/cogl-texture-2d-sliced.c | 30 ++++---
cogl/cogl-texture-2d.c | 28 +++---
cogl/cogl-texture-3d.c | 11 ++-
cogl/cogl-texture-driver.h | 13 +--
cogl/cogl-texture-private.h | 2 +
cogl/cogl-texture-rectangle.c | 5 +-
cogl/cogl-texture.c | 60 +++++-------
cogl/cogl-texture.h | 118 +++++++++++++++---------
cogl/driver/gl/cogl-texture-2d-gl-private.h | 16 ++--
cogl/driver/gl/cogl-texture-2d-gl.c | 41 +++++----
cogl/driver/gl/cogl-texture-gl-private.h | 17 ++++
cogl/driver/gl/cogl-texture-gl.c | 100 ++++++++++++++++++++
cogl/driver/gl/gl/cogl-texture-driver-gl.c | 84 ++++++++++++++---
cogl/driver/gl/gles/cogl-texture-driver-gles.c | 84 +++++++++++++----
cogl/driver/nop/cogl-texture-2d-nop-private.h | 16 ++--
cogl/driver/nop/cogl-texture-2d-nop.c | 16 ++--
cogl/winsys/cogl-texture-pixmap-x11.c | 17 +++-
tests/conform/test-alpha-textures.c | 5 +-
tests/conform/test-premult.c | 7 +-
tests/conform/test-sub-texture.c | 8 +-
tests/conform/test-write-texture-formats.c | 20 ++---
29 files changed, 563 insertions(+), 258 deletions(-)
diff --git a/cogl-pango/cogl-pango-render.c b/cogl-pango/cogl-pango-render.c
index 16f70b7..e296b2d 100644
--- a/cogl-pango/cogl-pango-render.c
+++ b/cogl-pango/cogl-pango-render.c
@@ -572,17 +572,14 @@ cogl_pango_renderer_set_dirty_glyph (PangoFont *font,
/* Copy the glyph to the texture */
cogl_texture_set_region (value->texture,
- 0, /* src_x */
- 0, /* src_y */
- value->tx_pixel, /* dst_x */
- value->ty_pixel, /* dst_y */
- value->draw_width, /* dst_width */
- value->draw_height, /* dst_height */
- value->draw_width, /* width */
- value->draw_height, /* height */
+ value->draw_width,
+ value->draw_height,
format_cogl,
cairo_image_surface_get_stride (surface),
cairo_image_surface_get_data (surface),
+ value->tx_pixel, /* dst_x */
+ value->ty_pixel, /* dst_y */
+ 0, /* level */
NULL); /* don't catch errors */
cairo_surface_destroy (surface);
diff --git a/cogl/cogl-atlas-texture.c b/cogl/cogl-atlas-texture.c
index f3f0910..0e8efcd 100644
--- a/cogl/cogl-atlas-texture.c
+++ b/cogl/cogl-atlas-texture.c
@@ -457,11 +457,12 @@ _cogl_atlas_texture_set_region_with_border (CoglAtlasTexture *atlas_tex,
/* Copy the central data */
if (!cogl_texture_set_region_from_bitmap (atlas->texture,
src_x, src_y,
- dst_x + atlas_tex->rectangle.x + 1,
- dst_y + atlas_tex->rectangle.y + 1,
dst_width,
dst_height,
bmp,
+ dst_x + atlas_tex->rectangle.x + 1,
+ dst_y + atlas_tex->rectangle.y + 1,
+ 0, /* level 0 */
error))
return FALSE;
@@ -469,42 +470,46 @@ _cogl_atlas_texture_set_region_with_border (CoglAtlasTexture *atlas_tex,
if (dst_x == 0 &&
!cogl_texture_set_region_from_bitmap (atlas->texture,
src_x, src_y,
- atlas_tex->rectangle.x,
- dst_y + atlas_tex->rectangle.y + 1,
1, dst_height,
bmp,
+ atlas_tex->rectangle.x,
+ dst_y + atlas_tex->rectangle.y + 1,
+ 0, /* level 0 */
error))
return FALSE;
/* Update the right edge pixels */
if (dst_x + dst_width == atlas_tex->rectangle.width - 2 &&
!cogl_texture_set_region_from_bitmap (atlas->texture,
src_x + dst_width - 1, src_y,
+ 1, dst_height,
+ bmp,
atlas_tex->rectangle.x +
atlas_tex->rectangle.width - 1,
dst_y + atlas_tex->rectangle.y + 1,
- 1, dst_height,
- bmp,
+ 0, /* level 0 */
error))
return FALSE;
/* Update the top edge pixels */
if (dst_y == 0 &&
!cogl_texture_set_region_from_bitmap (atlas->texture,
src_x, src_y,
- dst_x + atlas_tex->rectangle.x + 1,
- atlas_tex->rectangle.y,
dst_width, 1,
bmp,
+ dst_x + atlas_tex->rectangle.x + 1,
+ atlas_tex->rectangle.y,
+ 0, /* level 0 */
error))
return FALSE;
/* Update the bottom edge pixels */
if (dst_y + dst_height == atlas_tex->rectangle.height - 2 &&
!cogl_texture_set_region_from_bitmap (atlas->texture,
src_x, src_y + dst_height - 1,
+ dst_width, 1,
+ bmp,
dst_x + atlas_tex->rectangle.x + 1,
atlas_tex->rectangle.y +
atlas_tex->rectangle.height - 1,
- dst_width, 1,
- bmp,
+ 0, /* level 0 */
error))
return FALSE;
@@ -567,11 +572,15 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
int dst_y,
int dst_width,
int dst_height,
+ int level,
CoglBitmap *bmp,
CoglError **error)
{
CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
+ if (level != 0 && atlas_tex->atlas)
+ _cogl_atlas_texture_migrate_out_of_atlas (atlas_tex);
+
/* If the texture is in the atlas then we need to copy the edge
pixels to the border */
if (atlas_tex->atlas)
@@ -600,9 +609,10 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
/* Otherwise we can just forward on to the sub texture */
return cogl_texture_set_region_from_bitmap (atlas_tex->sub_texture,
src_x, src_y,
- dst_x, dst_y,
dst_width, dst_height,
bmp,
+ dst_x, dst_y,
+ level,
error);
}
diff --git a/cogl/cogl-blit.c b/cogl/cogl-blit.c
index d74356d..b6fcd7e 100644
--- a/cogl/cogl-blit.c
+++ b/cogl/cogl-blit.c
@@ -253,10 +253,11 @@ _cogl_blit_copy_tex_sub_image_blit (CoglBlitData *data,
int height)
{
_cogl_texture_2d_copy_from_framebuffer (COGL_TEXTURE_2D (data->dst_tex),
+ src_x, src_y,
+ width, height,
data->src_fb,
dst_x, dst_y,
- src_x, src_y,
- width, height);
+ 0); /* level */
}
static void
@@ -289,14 +290,16 @@ _cogl_blit_get_tex_data_blit (CoglBlitData *data,
int height)
{
CoglError *ignore = NULL;
+ int rowstride = data->src_width * data->bpp;
+ int offset = rowstride * src_y + src_x * data->bpp;
+
cogl_texture_set_region (data->dst_tex,
- src_x, src_y,
- dst_x, dst_y,
width, height,
- data->src_width, data->src_height,
data->format,
- data->src_width * data->bpp,
- data->image_data,
+ rowstride,
+ data->image_data + offset,
+ dst_x, dst_y,
+ 0, /* level */
&ignore);
/* TODO: support chaining up errors during the blit */
}
diff --git a/cogl/cogl-driver.h b/cogl/cogl-driver.h
index 6bfdcd6..ba6e030 100644
--- a/cogl/cogl-driver.h
+++ b/cogl/cogl-driver.h
@@ -168,13 +168,14 @@ struct _CoglDriverVtable
*/
void
(* texture_2d_copy_from_framebuffer) (CoglTexture2D *tex_2d,
- CoglFramebuffer *src_fb,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
- int height);
+ int height,
+ CoglFramebuffer *src_fb,
+ int dst_x,
+ int dst_y,
+ int level);
/* If the given texture has a corresponding OpenGL texture handle
* then return that.
@@ -196,13 +197,14 @@ struct _CoglDriverVtable
*/
CoglBool
(* texture_2d_copy_from_bitmap) (CoglTexture2D *tex_2d,
- CoglBitmap *bitmap,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
int height,
+ CoglBitmap *bitmap,
+ int dst_x,
+ int dst_y,
+ int level,
CoglError **error);
/* Reads back the full contents of the given texture and write it to
diff --git a/cogl/cogl-pipeline-layer-state.c b/cogl/cogl-pipeline-layer-state.c
index 5c05d16..e0dd294 100644
--- a/cogl/cogl-pipeline-layer-state.c
+++ b/cogl/cogl-pipeline-layer-state.c
@@ -1477,6 +1477,9 @@ cogl_pipeline_set_layer_filters (CoglPipeline *pipeline,
_COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline));
+ _COGL_RETURN_IF_FAIL (mag_filter == COGL_PIPELINE_FILTER_NEAREST ||
+ mag_filter == COGL_PIPELINE_FILTER_LINEAR);
+
/* Note: this will ensure that the layer exists, creating one if it
* doesn't already.
*
diff --git a/cogl/cogl-pipeline-layer-state.h b/cogl/cogl-pipeline-layer-state.h
index c8e0d0e..3241326 100644
--- a/cogl/cogl-pipeline-layer-state.h
+++ b/cogl/cogl-pipeline-layer-state.h
@@ -340,6 +340,11 @@ cogl_pipeline_get_n_layers (CoglPipeline *pipeline);
* Changes the decimation and interpolation filters used when a texture is
* drawn at other scales than 100%.
*
+ * <note>It is an error to pass anything other than
+ * %COGL_PIPELINE_FILTER_NEAREST or %COGL_PIPELINE_FILTER_LINEAR as
+ * magnification filters since magnification doesn't ever need to
+ * reference values stored in the mipmap chain.</note>
+ *
* Since: 1.10
* Stability: unstable
*/
diff --git a/cogl/cogl-sub-texture.c b/cogl/cogl-sub-texture.c
index fb2cf8e..915277f 100644
--- a/cogl/cogl-sub-texture.c
+++ b/cogl/cogl-sub-texture.c
@@ -374,17 +374,32 @@ _cogl_sub_texture_set_region (CoglTexture *tex,
int dst_y,
int dst_width,
int dst_height,
+ int level,
CoglBitmap *bmp,
CoglError **error)
{
CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
+ if (level != 0)
+ {
+ int full_width = cogl_texture_get_width (sub_tex->full_texture);
+ int full_height = cogl_texture_get_width (sub_tex->full_texture);
+
+ _COGL_RETURN_VAL_IF_FAIL (sub_tex->sub_x == 0 &&
+ cogl_texture_get_width (tex) == full_width,
+ FALSE);
+ _COGL_RETURN_VAL_IF_FAIL (sub_tex->sub_y == 0 &&
+ cogl_texture_get_height (tex) == full_height,
+ FALSE);
+ }
+
return cogl_texture_set_region_from_bitmap (sub_tex->full_texture,
src_x, src_y,
- dst_x + sub_tex->sub_x,
- dst_y + sub_tex->sub_y,
dst_width, dst_height,
bmp,
+ dst_x + sub_tex->sub_x,
+ dst_y + sub_tex->sub_y,
+ level,
error);
}
diff --git a/cogl/cogl-texture-2d-private.h b/cogl/cogl-texture-2d-private.h
index aa5a35e..39c9f25 100644
--- a/cogl/cogl-texture-2d-private.h
+++ b/cogl/cogl-texture-2d-private.h
@@ -51,7 +51,7 @@ struct _CoglTexture2D
* of driver private state. */
/* The internal format of the GL texture represented as a GL enum */
- GLenum gl_format;
+ GLenum gl_internal_format;
/* The texture object number */
GLuint gl_texture;
GLenum gl_legacy_texobj_min_filter;
@@ -98,25 +98,27 @@ _cogl_texture_2d_externally_modified (CoglTexture *texture);
/*
* _cogl_texture_2d_copy_from_framebuffer:
* @texture: A #CoglTexture2D pointer
- * @src_fb: A source #CoglFramebuffer to copy from
- * @dst_x: X-position to store the image within the texture
- * @dst_y: Y-position to store the image within the texture
* @src_x: X-position to within the framebuffer to read from
* @src_y: Y-position to within the framebuffer to read from
* @width: width of the rectangle to copy
* @height: height of the rectangle to copy
+ * @src_fb: A source #CoglFramebuffer to copy from
+ * @dst_x: X-position to store the image within the texture
+ * @dst_y: Y-position to store the image within the texture
+ * @level: The mipmap level of @texture to copy too
*
* This copies a portion of the given @src_fb into the
* texture.
*/
void
_cogl_texture_2d_copy_from_framebuffer (CoglTexture2D *texture,
- CoglFramebuffer *src_fb,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
- int height);
+ int height,
+ CoglFramebuffer *src_fb,
+ int dst_x,
+ int dst_y,
+ int level);
#endif /* __COGL_TEXTURE_2D_PRIVATE_H */
diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c
index 2978454..6d1f530 100644
--- a/cogl/cogl-texture-2d-sliced.c
+++ b/cogl/cogl-texture-2d-sliced.c
@@ -48,6 +48,7 @@
#include "cogl-pipeline-opengl-private.h"
#include "cogl-primitive-texture.h"
#include "cogl-error-private.h"
+#include "cogl-texture-gl-private.h"
#include <string.h>
#include <stdlib.h>
@@ -238,15 +239,16 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds,
if (!cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex),
0, /* src_x */
0, /* src_y */
+ x_span->waste, /* width */
+ /* height */
+ y_iter->intersect_end -
+ y_iter->intersect_start,
+ waste_bmp,
/* dst_x */
x_span->size - x_span->waste,
y_iter->intersect_start -
y_span->start, /* dst_y */
- x_span->waste, /* dst_width */
- /* dst_height */
- y_iter->intersect_end -
- y_iter->intersect_start,
- waste_bmp,
+ 0, /* level */
error))
{
cogl_object_unref (waste_bmp);
@@ -298,14 +300,15 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds,
if (!cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex),
0, /* src_x */
0, /* src_y */
+ copy_width, /* width */
+ y_span->waste, /* height */
+ waste_bmp,
/* dst_x */
x_iter->intersect_start -
x_iter->pos,
/* dst_y */
y_span->size - y_span->waste,
- copy_width, /* dst_width */
- y_span->waste, /* dst_height */
- waste_bmp,
+ 0, /* level */
error))
{
cogl_object_unref (waste_bmp);
@@ -359,13 +362,14 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
if (!cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_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 */
bmp,
+ 0, /* dst x */
+ 0, /* dst y */
+ 0, /* level */
error))
{
if (waste_buf)
@@ -495,11 +499,12 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
if (!cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex),
source_x,
source_y,
- local_x, /* dst x */
- local_y, /* dst y */
inter_w, /* width */
inter_h, /* height */
source_bmp,
+ local_x, /* dst x */
+ local_y, /* dst y */
+ 0, /* level */
error))
{
if (waste_buf)
@@ -1286,6 +1291,7 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex,
int dst_y,
int dst_width,
int dst_height,
+ int level,
CoglBitmap *bmp,
CoglError **error)
{
diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c
index 853e646..9df370d 100644
--- a/cogl/cogl-texture-2d.c
+++ b/cogl/cogl-texture-2d.c
@@ -343,24 +343,26 @@ _cogl_texture_2d_externally_modified (CoglTexture *texture)
void
_cogl_texture_2d_copy_from_framebuffer (CoglTexture2D *tex_2d,
- CoglFramebuffer *src_fb,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
- int height)
+ int height,
+ CoglFramebuffer *src_fb,
+ int dst_x,
+ int dst_y,
+ int level)
{
CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;
ctx->driver_vtable->texture_2d_copy_from_framebuffer (tex_2d,
- src_fb,
- dst_x,
- dst_y,
src_x,
src_y,
width,
- height);
+ height,
+ src_fb,
+ dst_x,
+ dst_y,
+ level);
tex_2d->mipmaps_dirty = TRUE;
}
@@ -479,6 +481,7 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
int dst_y,
int width,
int height,
+ int level,
CoglBitmap *bmp,
CoglError **error)
{
@@ -486,13 +489,14 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
if (!ctx->driver_vtable->texture_2d_copy_from_bitmap (tex_2d,
- bmp,
- dst_x,
- dst_y,
src_x,
src_y,
width,
height,
+ bmp,
+ dst_x,
+ dst_y,
+ level,
error))
{
return FALSE;
@@ -530,7 +534,7 @@ _cogl_texture_2d_get_format (CoglTexture *tex)
static GLenum
_cogl_texture_2d_get_gl_format (CoglTexture *tex)
{
- return COGL_TEXTURE_2D (tex)->gl_format;
+ return COGL_TEXTURE_2D (tex)->gl_internal_format;
}
static int
diff --git a/cogl/cogl-texture-3d.c b/cogl/cogl-texture-3d.c
index 0b3fa81..e7a9051 100644
--- a/cogl/cogl-texture-3d.c
+++ b/cogl/cogl-texture-3d.c
@@ -31,6 +31,7 @@
#include "cogl-texture-private.h"
#include "cogl-texture-3d-private.h"
#include "cogl-texture-3d.h"
+#include "cogl-texture-gl-private.h"
#include "cogl-texture-driver.h"
#include "cogl-context-private.h"
#include "cogl-object-private.h"
@@ -547,17 +548,18 @@ _cogl_texture_3d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
if ((flags & COGL_TEXTURE_NEEDS_MIPMAP) &&
tex_3d->auto_mipmap && tex_3d->mipmaps_dirty)
{
- _cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
- tex_3d->gl_texture,
- FALSE);
/* glGenerateMipmap is defined in the FBO extension. If it's not
available we'll fallback to temporarily enabling
GL_GENERATE_MIPMAP and reuploading the first pixel */
if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
- ctx->texture_driver->gl_generate_mipmaps (ctx, GL_TEXTURE_3D);
+ _cogl_texture_gl_generate_mipmaps (tex);
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
else if (ctx->driver != COGL_DRIVER_GLES2)
{
+ _cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
+ tex_3d->gl_texture,
+ FALSE);
+
GE( ctx, glTexParameteri (GL_TEXTURE_3D,
GL_GENERATE_MIPMAP,
GL_TRUE) );
@@ -596,6 +598,7 @@ _cogl_texture_3d_set_region (CoglTexture *tex,
int dst_y,
int dst_width,
int dst_height,
+ int level,
CoglBitmap *bmp,
CoglError **error)
{
diff --git a/cogl/cogl-texture-driver.h b/cogl/cogl-texture-driver.h
index 780f40d..8ab8655 100644
--- a/cogl/cogl-texture-driver.h
+++ b/cogl/cogl-texture-driver.h
@@ -65,8 +65,7 @@ struct _CoglTextureDriver
*/
CoglBool
(* upload_subregion_to_gl) (CoglContext *ctx,
- GLenum gl_target,
- GLuint gl_handle,
+ CoglTexture *texture,
CoglBool is_foreign,
int src_x,
int src_y,
@@ -74,6 +73,7 @@ struct _CoglTextureDriver
int dst_y,
int width,
int height,
+ int level,
CoglBitmap *source_bmp,
GLuint source_gl_format,
GLuint source_gl_type,
@@ -183,15 +183,6 @@ struct _CoglTextureDriver
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
- (* gl_generate_mipmaps) (CoglContext *ctx,
- 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
diff --git a/cogl/cogl-texture-private.h b/cogl/cogl-texture-private.h
index 1619277..49c3117 100644
--- a/cogl/cogl-texture-private.h
+++ b/cogl/cogl-texture-private.h
@@ -72,6 +72,7 @@ struct _CoglTextureVtable
int dst_y,
int dst_width,
int dst_height,
+ int level,
CoglBitmap *bitmap,
CoglError **error);
@@ -142,6 +143,7 @@ struct _CoglTexture
CoglObject _parent;
CoglContext *context;
GList *framebuffers;
+ int max_level;
const CoglTextureVtable *vtable;
};
diff --git a/cogl/cogl-texture-rectangle.c b/cogl/cogl-texture-rectangle.c
index e8bb965..9ce8810 100644
--- a/cogl/cogl-texture-rectangle.c
+++ b/cogl/cogl-texture-rectangle.c
@@ -554,6 +554,7 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex,
int dst_y,
int dst_width,
int dst_height,
+ int level,
CoglBitmap *bmp,
CoglError **error)
{
@@ -576,12 +577,12 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex,
/* Send data to GL */
status =
ctx->texture_driver->upload_subregion_to_gl (ctx,
- GL_TEXTURE_RECTANGLE_ARB,
- tex_rect->gl_texture,
+ tex,
FALSE,
src_x, src_y,
dst_x, dst_y,
dst_width, dst_height,
+ level,
bmp,
gl_format,
gl_type,
diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c
index 6958160..bd4cdba 100644
--- a/cogl/cogl-texture.c
+++ b/cogl/cogl-texture.c
@@ -104,6 +104,7 @@ _cogl_texture_init (CoglTexture *texture,
const CoglTextureVtable *vtable)
{
texture->context = context;
+ texture->max_level = 0;
texture->vtable = vtable;
texture->framebuffers = NULL;
}
@@ -343,22 +344,21 @@ CoglBool
cogl_texture_set_region_from_bitmap (CoglTexture *texture,
int src_x,
int src_y,
+ int width,
+ int height,
+ CoglBitmap *bmp,
int dst_x,
int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp,
+ int level,
CoglError **error)
{
- CoglBool ret;
-
_COGL_RETURN_VAL_IF_FAIL ((cogl_bitmap_get_width (bmp) - src_x)
- >= dst_width, FALSE);
+ >= width, FALSE);
_COGL_RETURN_VAL_IF_FAIL ((cogl_bitmap_get_height (bmp) - src_y)
- >= dst_height, FALSE);
+ >= height, FALSE);
/* Shortcut out early if the image is empty */
- if (dst_width == 0 || dst_height == 0)
+ if (width == 0 || height == 0)
return TRUE;
/* Note that we don't prepare the bitmap for upload here because
@@ -368,41 +368,32 @@ cogl_texture_set_region_from_bitmap (CoglTexture *texture,
always stored in an RGBA texture even if the texture format is
advertised as RGB. */
- ret = texture->vtable->set_region (texture,
- src_x, src_y,
- dst_x, dst_y,
- dst_width, dst_height,
- bmp,
- error);
-
- return ret;
+ return texture->vtable->set_region (texture,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height,
+ level,
+ bmp,
+ error);
}
CoglBool
cogl_texture_set_region (CoglTexture *texture,
- int src_x,
- int src_y,
+ int width,
+ int height,
+ CoglPixelFormat format,
+ int rowstride,
+ const uint8_t *data,
int dst_x,
int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- int width,
- int height,
- CoglPixelFormat format,
- unsigned int rowstride,
- const uint8_t *data,
+ int level,
CoglError **error)
{
CoglContext *ctx = texture->context;
CoglBitmap *source_bmp;
CoglBool ret;
- _COGL_RETURN_VAL_IF_FAIL ((width - src_x) >= dst_width, FALSE);
- _COGL_RETURN_VAL_IF_FAIL ((height - src_y) >= dst_height, FALSE);
-
- /* Check for valid format */
- if (format == COGL_PIXEL_FORMAT_ANY)
- return FALSE;
+ _COGL_RETURN_VAL_IF_FAIL (format != COGL_PIXEL_FORMAT_ANY, FALSE);
/* Rowstride from width if none specified */
if (rowstride == 0)
@@ -416,10 +407,11 @@ cogl_texture_set_region (CoglTexture *texture,
(uint8_t *) data);
ret = cogl_texture_set_region_from_bitmap (texture,
- src_x, src_y,
- dst_x, dst_y,
- dst_width, dst_height,
+ 0, 0,
+ width, height,
source_bmp,
+ dst_x, dst_y,
+ level,
error);
cogl_object_unref (source_bmp);
diff --git a/cogl/cogl-texture.h b/cogl/cogl-texture.h
index 77a269b..a0ecab4 100644
--- a/cogl/cogl-texture.h
+++ b/cogl/cogl-texture.h
@@ -401,64 +401,95 @@ cogl_texture_draw_and_read_to_bitmap (CoglTexture *texture,
/**
* cogl_texture_set_region:
* @texture a #CoglTexture.
- * @src_x: upper left coordinate to use from source data.
- * @src_y: upper left coordinate to use from source data.
- * @dst_x: upper left destination horizontal coordinate.
- * @dst_y: upper left destination vertical coordinate.
- * @dst_width: width of destination region to write. (Must be less
- * than or equal to @width)
- * @dst_height: height of destination region to write. (Must be less
- * than or equal to @height)
- * @width: width of source data buffer.
- * @height: height of source data buffer.
- * @format: the #CoglPixelFormat used in the source buffer.
- * @rowstride: rowstride of source buffer (computed from width if none
- * specified)
- * @data: the actual pixel data.
+ * @width: width of the region to set.
+ * @height: height of the region to set.
+ * @format: the #CoglPixelFormat used in the source @data buffer.
+ * @rowstride: rowstride in bytes of the source @data buffer (computed
+ * from @width and @format if it equals 0)
+ * @data: the source data, pointing to the first top-left pixel to set
+ * @dst_x: upper left destination x coordinate.
+ * @dst_y: upper left destination y coordinate.
+ * @level: The mipmap level to update (Normally 0 for the largest,
+ * base image)
* @error: A #CoglError to return exceptional errors
*
- * Sets the pixels in a rectangular subregion of @texture from an in-memory
- * buffer containing pixel data.
+ * Sets the pixels in a rectangular subregion of @texture from an
+ * in-memory buffer containing pixel @data.
*
- * <note>The region set can't be larger than the source @data</note>
+ * @data should point to the first pixel to copy corresponding
+ * to the top left of the region being set.
+ *
+ * The rowstride determines how many bytes between the first pixel of
+ * a row of @data and the first pixel of the next row. If @rowstride
+ * equals 0 then it will be automatically calculated from @width and
+ * the bytes-per-pixel for the given @format.
+ *
+ * A mipmap @level of 0 corresponds to the largest, base image of a
+ * texture and @level 1 is half the width and height of level 0. If
+ * dividing any dimension of the previous level by two results in a
+ * fraction then round the number down (floor()), but clamp to 1
+ * something like this:
+ *
+ * |[
+ * next_width = MAX (1, floor (prev_width));
+ * ]|
+ *
+ * You can determine the number of mipmap levels for a given texture
+ * like this:
+ *
+ * |[
+ * n_levels = 1 + floor (log2 (max_dimension));
+ * ]|
+ *
+ * Where %max_dimension is the larger of cogl_texture_get_width() and
+ * cogl_texture_get_height().
+ *
+ * It is an error to pass a @level number >= the number of levels that
+ * @texture can have according to the above calculation.
+ *
+ * <note>Since the storage for a #CoglTexture is allocated lazily then
+ * if the given @texture has not previously been allocated then this
+ * api can return %FALSE and throw an exceptional @error if there is
+ * not enough memory to allocate storage for @texture.</note>
*
* Return value: %TRUE if the subregion upload was successful, and
* %FALSE otherwise
*/
CoglBool
cogl_texture_set_region (CoglTexture *texture,
- 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,
+ int rowstride,
const uint8_t *data,
+ int dst_x,
+ int dst_y,
+ int level,
CoglError **error);
/**
* cogl_texture_set_region_from_bitmap:
* @texture a #CoglTexture pointer
- * @src_x: upper left coordinate to use from the source bitmap.
- * @src_y: upper left coordinate to use from the source bitmap
- * @dst_x: upper left destination horizontal coordinate.
- * @dst_y: upper left destination vertical coordinate.
- * @dst_width: width of destination region to write. (Must be less
- * than or equal to the bitmap width)
- * @dst_height: height of destination region to write. (Must be less
- * than or equal to the bitmap height)
- * @bitmap: The source bitmap to read from
- * @error: A #CoglError to return exceptional errors
- *
- * Copies a specified source region from @bitmap to the position
- * (@src_x, @src_y) of the given destination texture @handle.
- *
- * <note>The region updated can't be larger than the source
- * bitmap</note>
+ * @src_x: upper left x coordinate of the region in the source bitmap.
+ * @src_y: upper left y coordinate of the region in the source bitmap
+ * @width: width of the region to copy. (Must be less than or equal to
+ * the bitmap width)
+ * @height: height of the region to copy. (Must be less than or equal
+ * to the bitmap height)
+ * @bitmap: The source bitmap to copy from
+ * @dst_x: upper left destination x coordinate to copy to.
+ * @dst_y: upper left destination y coordinate to copy to.
+ * @error: A #CoglError to return exceptional errors or %NULL
+ *
+ * Copies a rectangular region from @bitmap to the position
+ * (@dst_x, @dst_y) of the given destination @texture.
+ *
+ * The source region's top left coordinate is (@src_x, @src_y) within
+ * the source @bitmap and the region is @width pixels wide and @height
+ * pixels high.
+ *
+ * <note>The source region must not extend outside the bounds of the
+ * source @bitmap.</note>
*
* Return value: %TRUE if the subregion upload was successful, and
* %FALSE otherwise
@@ -470,11 +501,12 @@ CoglBool
cogl_texture_set_region_from_bitmap (CoglTexture *texture,
int src_x,
int src_y,
+ int width,
+ int height,
+ CoglBitmap *bitmap,
int dst_x,
int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bitmap,
+ int level,
CoglError **error);
COGL_END_DECLS
diff --git a/cogl/driver/gl/cogl-texture-2d-gl-private.h b/cogl/driver/gl/cogl-texture-2d-gl-private.h
index ac0c89f..d77f460 100644
--- a/cogl/driver/gl/cogl-texture-2d-gl-private.h
+++ b/cogl/driver/gl/cogl-texture-2d-gl-private.h
@@ -79,13 +79,14 @@ _cogl_texture_2d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
void
_cogl_texture_2d_gl_copy_from_framebuffer (CoglTexture2D *tex_2d,
- CoglFramebuffer *src_fb,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
- int height);
+ int height,
+ CoglFramebuffer *src_fb,
+ int dst_x,
+ int dst_y,
+ int level);
unsigned int
_cogl_texture_2d_gl_get_gl_handle (CoglTexture2D *tex_2d);
@@ -95,13 +96,14 @@ _cogl_texture_2d_gl_generate_mipmap (CoglTexture2D *tex_2d);
CoglBool
_cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
- CoglBitmap *bitmap,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
int height,
+ CoglBitmap *bitmap,
+ int dst_x,
+ int dst_y,
+ int level,
CoglError **error);
void
diff --git a/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/driver/gl/cogl-texture-2d-gl.c
index dd08401..dadbc19 100644
--- a/cogl/driver/gl/cogl-texture-2d-gl.c
+++ b/cogl/driver/gl/cogl-texture-2d-gl.c
@@ -35,6 +35,7 @@
#include "cogl-texture-2d-gl.h"
#include "cogl-texture-2d-gl-private.h"
#include "cogl-texture-2d-private.h"
+#include "cogl-texture-gl-private.h"
#include "cogl-pipeline-opengl-private.h"
#include "cogl-error-private.h"
#include "cogl-util-gl-private.h"
@@ -112,6 +113,9 @@ _cogl_texture_2d_gl_new_with_size (CoglContext *ctx,
tex_2d->gl_texture =
ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, internal_format);
+
+ tex_2d->gl_internal_format = gl_intformat;
+
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
tex_2d->gl_texture,
tex_2d->is_foreign);
@@ -205,7 +209,7 @@ _cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
return NULL;
}
- tex_2d->gl_format = gl_intformat;
+ tex_2d->gl_internal_format = gl_intformat;
cogl_object_unref (dst_bmp);
@@ -441,7 +445,7 @@ cogl_texture_2d_gl_new_from_foreign (CoglContext *ctx,
tex_2d->format = format;
tex_2d->gl_texture = gl_handle;
- tex_2d->gl_format = gl_int_format;
+ tex_2d->gl_internal_format = gl_int_format;
/* Unknown filter */
tex_2d->gl_legacy_texobj_min_filter = GL_FALSE;
@@ -452,13 +456,14 @@ cogl_texture_2d_gl_new_from_foreign (CoglContext *ctx,
void
_cogl_texture_2d_gl_copy_from_framebuffer (CoglTexture2D *tex_2d,
- CoglFramebuffer *src_fb,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
- int height)
+ int height,
+ CoglFramebuffer *src_fb,
+ int dst_x,
+ int dst_y,
+ int level)
{
CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;
@@ -492,18 +497,18 @@ _cogl_texture_2d_gl_generate_mipmap (CoglTexture2D *tex_2d)
{
CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
-
/* glGenerateMipmap is defined in the FBO extension. If it's not
available we'll fallback to temporarily enabling
GL_GENERATE_MIPMAP and reuploading the first pixel */
if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
- ctx->texture_driver->gl_generate_mipmaps (ctx, GL_TEXTURE_2D);
+ _cogl_texture_gl_generate_mipmaps (COGL_TEXTURE (tex_2d));
#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL)
else
{
+ _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
+ tex_2d->gl_texture,
+ tex_2d->is_foreign);
+
GE( ctx, glTexParameteri (GL_TEXTURE_2D,
GL_GENERATE_MIPMAP,
GL_TRUE) );
@@ -520,13 +525,14 @@ _cogl_texture_2d_gl_generate_mipmap (CoglTexture2D *tex_2d)
CoglBool
_cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
- CoglBitmap *bmp,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
int height,
+ CoglBitmap *bmp,
+ int dst_x,
+ int dst_y,
+ int level,
CoglError **error)
{
CoglTexture *tex = COGL_TEXTURE (tex_2d);
@@ -574,14 +580,13 @@ _cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
}
}
- /* Send data to GL */
status = ctx->texture_driver->upload_subregion_to_gl (ctx,
- GL_TEXTURE_2D,
- tex_2d->gl_texture,
+ tex,
FALSE,
src_x, src_y,
dst_x, dst_y,
width, height,
+ level,
bmp,
gl_format,
gl_type,
@@ -589,6 +594,8 @@ _cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
cogl_object_unref (bmp);
+ _cogl_texture_gl_maybe_update_max_level (tex, level);
+
return status;
}
diff --git a/cogl/driver/gl/cogl-texture-gl-private.h b/cogl/driver/gl/cogl-texture-gl-private.h
index b44861c..f91de0c 100644
--- a/cogl/driver/gl/cogl-texture-gl-private.h
+++ b/cogl/driver/gl/cogl-texture-gl-private.h
@@ -46,4 +46,21 @@ _cogl_texture_gl_flush_legacy_texobj_filters (CoglTexture *texture,
unsigned int min_filter,
unsigned int mag_filter);
+int
+_cogl_texture_gl_get_n_levels (CoglTexture *texture);
+
+void
+_cogl_texture_gl_get_level_size (CoglTexture *texture,
+ int level,
+ int *width,
+ int *height,
+ int *depth);
+
+void
+_cogl_texture_gl_maybe_update_max_level (CoglTexture *texture,
+ int max_level);
+
+void
+_cogl_texture_gl_generate_mipmaps (CoglTexture *texture);
+
#endif /* _COGL_TEXTURE_GL_PRIVATE_H_ */
diff --git a/cogl/driver/gl/cogl-texture-gl.c b/cogl/driver/gl/cogl-texture-gl.c
index a9f0d32..508fe04 100644
--- a/cogl/driver/gl/cogl-texture-gl.c
+++ b/cogl/driver/gl/cogl-texture-gl.c
@@ -29,7 +29,9 @@
#include "cogl-internal.h"
#include "cogl-context-private.h"
#include "cogl-texture-gl-private.h"
+#include "cogl-texture-3d-private.h"
#include "cogl-util.h"
+#include "cogl-pipeline-opengl-private.h"
static inline int
calculate_alignment (int rowstride)
@@ -92,3 +94,101 @@ _cogl_texture_gl_flush_legacy_texobj_filters (CoglTexture *texture,
texture->vtable->gl_flush_legacy_texobj_filters (texture,
min_filter, mag_filter);
}
+
+int
+_cogl_texture_gl_get_n_levels (CoglTexture *texture)
+{
+ int width = cogl_texture_get_width (texture);
+ int height = cogl_texture_get_height (texture);
+ int max_dimension = MAX (width, height);
+
+ if (cogl_is_texture_3d (texture))
+ {
+ CoglTexture3D *tex_3d = COGL_TEXTURE_3D (texture);
+ max_dimension = MAX (max_dimension, tex_3d->depth);
+ }
+
+ /* The OpenGL spec clarifies that this is how you can calculate the
+ * number of mipmap levels a texture requires... */
+ return 1 + floorf (log2f (max_dimension));
+}
+
+void
+_cogl_texture_gl_get_level_size (CoglTexture *texture,
+ int level,
+ int *width,
+ int *height,
+ int *depth)
+{
+ int current_width = cogl_texture_get_width (texture);
+ int current_height = cogl_texture_get_height (texture);
+ int current_depth;
+ int i;
+
+ if (cogl_is_texture_3d (texture))
+ {
+ CoglTexture3D *tex_3d = COGL_TEXTURE_3D (texture);
+ current_depth = tex_3d->depth;
+ }
+ else
+ current_depth = 0;
+
+ /* NB: The OpenGL spec (like D3D) uses a floor() convention to
+ * round down the size of a mipmap level when dividing the size
+ * of the previous level results in a fraction...
+ */
+ for (i = 0; i < level; i++)
+ {
+ current_width = MAX (1, current_width >> 1);
+ current_height = MAX (1, current_height >> 1);
+ current_depth = MAX (1, current_depth >> 1);
+ }
+
+ if (width)
+ *width = current_width;
+ if (height)
+ *height = current_height;
+ if (depth)
+ *depth = current_depth;
+}
+
+void
+_cogl_texture_gl_maybe_update_max_level (CoglTexture *texture,
+ int max_level)
+{
+ if (texture->max_level < max_level)
+ {
+ CoglContext *ctx = texture->context;
+ GLuint gl_handle;
+ GLenum gl_target;
+
+ cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);
+
+ texture->max_level = max_level;
+
+ _cogl_bind_gl_texture_transient (gl_target,
+ gl_handle,
+ _cogl_texture_is_foreign (texture));
+
+ GE( ctx, glTexParameteri (gl_target,
+ GL_TEXTURE_MAX_LEVEL, texture->max_level));
+ }
+}
+
+void
+_cogl_texture_gl_generate_mipmaps (CoglTexture *texture)
+{
+ CoglContext *ctx = texture->context;
+ int n_levels = _cogl_texture_gl_get_n_levels (texture);
+ GLuint gl_handle;
+ GLenum gl_target;
+
+ _cogl_texture_gl_maybe_update_max_level (texture, n_levels - 1);
+
+ cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);
+
+ _cogl_bind_gl_texture_transient (gl_target,
+ gl_handle,
+ _cogl_texture_is_foreign (texture));
+ GE( ctx, glGenerateMipmap (gl_target) );
+}
diff --git a/cogl/driver/gl/gl/cogl-texture-driver-gl.c b/cogl/driver/gl/gl/cogl-texture-driver-gl.c
index 0e72ac9..14918cb 100644
--- a/cogl/driver/gl/gl/cogl-texture-driver-gl.c
+++ b/cogl/driver/gl/gl/cogl-texture-driver-gl.c
@@ -66,6 +66,14 @@ _cogl_texture_driver_gen (CoglContext *ctx,
{
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
+ /* In case automatic mipmap generation gets disabled for this
+ * texture but a minification filter depending on mipmap
+ * interpolation is selected then we initialize the max mipmap
+ * level to 0 so OpenGL will consider the texture storage to be
+ * "complete".
+ */
+ GE( ctx, glTexParameteri (gl_target, GL_TEXTURE_MAX_LEVEL, 0));
+
/* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
GE( ctx, glTexParameteri (gl_target,
GL_TEXTURE_MIN_FILTER,
@@ -169,8 +177,7 @@ _cogl_texture_driver_prep_gl_for_pixels_download (CoglContext *ctx,
static CoglBool
_cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
- GLenum gl_target,
- GLuint gl_handle,
+ CoglTexture *texture,
CoglBool is_foreign,
int src_x,
int src_y,
@@ -178,17 +185,24 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
int dst_y,
int width,
int height,
+ int level,
CoglBitmap *source_bmp,
GLuint source_gl_format,
GLuint source_gl_type,
CoglError **error)
{
+ GLenum gl_target;
+ GLuint gl_handle;
uint8_t *data;
CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format);
GLenum gl_error;
CoglBool status = TRUE;
CoglError *internal_error = NULL;
+ int level_width;
+ int level_height;
+
+ cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);
data = _cogl_bitmap_gl_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0, &internal_error);
@@ -215,12 +229,58 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
;
- ctx->glTexSubImage2D (gl_target, 0,
- dst_x, dst_y,
- width, height,
- source_gl_format,
- source_gl_type,
- data);
+ _cogl_texture_gl_get_level_size (texture,
+ level,
+ &level_width,
+ &level_height,
+ NULL);
+
+ if (level_width == width && level_height == height)
+ {
+ /* GL gets upset if you use glTexSubImage2D to initialize the
+ * contents of a mipmap level so we make sure to use
+ * glTexImage2D if we are uploading a full mipmap level.
+ */
+ ctx->glTexImage2D (gl_target,
+ level,
+ _cogl_texture_get_gl_format (texture),
+ width,
+ height,
+ 0,
+ source_gl_format,
+ source_gl_type,
+ data);
+
+ }
+ else
+ {
+ /* GL gets upset if you use glTexSubImage2D to initialize the
+ * contents of a mipmap level so if this is the first time
+ * we've seen a request to upload to this level we call
+ * glTexImage2D first to assert that the storage for this
+ * level exists.
+ */
+ if (texture->max_level < level)
+ {
+ ctx->glTexImage2D (gl_target,
+ level,
+ _cogl_texture_get_gl_format (texture),
+ level_width,
+ level_height,
+ 0,
+ source_gl_format,
+ source_gl_type,
+ NULL);
+ }
+
+ ctx->glTexSubImage2D (gl_target,
+ level,
+ dst_x, dst_y,
+ width, height,
+ source_gl_format,
+ source_gl_type,
+ data);
+ }
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
status = FALSE;
@@ -441,13 +501,6 @@ _cogl_texture_driver_allows_foreign_gl_target (CoglContext *ctx,
return TRUE;
}
-static void
-_cogl_texture_driver_gl_generate_mipmaps (CoglContext *ctx,
- GLenum gl_target)
-{
- GE( ctx, glGenerateMipmap (gl_target) );
-}
-
static CoglPixelFormat
_cogl_texture_driver_find_best_gl_get_data_format
(CoglContext *context,
@@ -476,6 +529,5 @@ _cogl_texture_driver_gl =
_cogl_texture_driver_size_supported_3d,
_cogl_texture_driver_try_setting_gl_border_color,
_cogl_texture_driver_allows_foreign_gl_target,
- _cogl_texture_driver_gl_generate_mipmaps,
_cogl_texture_driver_find_best_gl_get_data_format
};
diff --git a/cogl/driver/gl/gles/cogl-texture-driver-gles.c b/cogl/driver/gl/gles/cogl-texture-driver-gles.c
index f13f278..a3efd9e 100644
--- a/cogl/driver/gl/gles/cogl-texture-driver-gles.c
+++ b/cogl/driver/gl/gles/cogl-texture-driver-gles.c
@@ -81,6 +81,14 @@ _cogl_texture_driver_gen (CoglContext *ctx,
{
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
+ /* In case automatic mipmap generation gets disabled for this
+ * texture but a minification filter depending on mipmap
+ * interpolation is selected then we initialize the max mipmap
+ * level to 0 so OpenGL will consider the texture storage to be
+ * "complete".
+ */
+ GE( ctx, glTexParameteri (gl_target, GL_TEXTURE_MAX_LEVEL, 0));
+
/* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
GE( ctx, glTexParameteri (gl_target,
GL_TEXTURE_MIN_FILTER,
@@ -172,8 +180,7 @@ prepare_bitmap_alignment_for_upload (CoglContext *ctx,
static CoglBool
_cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
- GLenum gl_target,
- GLuint gl_handle,
+ CoglTexture *texture,
CoglBool is_foreign,
int src_x,
int src_y,
@@ -181,11 +188,14 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
int dst_y,
int width,
int height,
+ int level,
CoglBitmap *source_bmp,
GLuint source_gl_format,
GLuint source_gl_type,
CoglError **error)
{
+ GLenum gl_target;
+ GLuint gl_handle;
uint8_t *data;
CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format);
@@ -194,6 +204,10 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
GLenum gl_error;
CoglBool status = TRUE;
CoglError *internal_error = NULL;
+ int level_width;
+ int level_height;
+
+ cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);
/* If we have the GL_EXT_unpack_subimage extension then we can
upload from subregions directly. Otherwise we may need to copy
@@ -254,12 +268,57 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
;
- ctx->glTexSubImage2D (gl_target, 0,
- dst_x, dst_y,
- width, height,
- source_gl_format,
- source_gl_type,
- data);
+ _cogl_texture_gl_get_level_size (texture,
+ level,
+ &level_width,
+ &level_height,
+ NULL);
+
+ if (level_width == width && level_height == height)
+ {
+ /* GL gets upset if you use glTexSubImage2D to define the
+ * contents of a mipmap level so we make sure to use
+ * glTexImage2D if we are uploading a full mipmap level.
+ */
+ ctx->glTexImage2D (gl_target,
+ level,
+ _cogl_texture_get_gl_format (texture),
+ width,
+ height,
+ 0,
+ source_gl_format,
+ source_gl_type,
+ data);
+ }
+ else
+ {
+ /* GL gets upset if you use glTexSubImage2D to initialize the
+ * contents of a mipmap level so if this is the first time
+ * we've seen a request to upload to this level we call
+ * glTexImage2D first to assert that the storage for this
+ * level exists.
+ */
+ if (texture->max_level < level)
+ {
+ ctx->glTexImage2D (gl_target,
+ level,
+ _cogl_texture_get_gl_format (texture),
+ level_width,
+ level_height,
+ 0,
+ source_gl_format,
+ source_gl_type,
+ NULL);
+ }
+
+ ctx->glTexSubImage2D (gl_target,
+ level,
+ dst_x, dst_y,
+ width, height,
+ source_gl_format,
+ source_gl_type,
+ data);
+ }
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
status = FALSE;
@@ -551,14 +610,6 @@ _cogl_texture_driver_allows_foreign_gl_target (CoglContext *ctx,
return TRUE;
}
-static void
-_cogl_texture_driver_gl_generate_mipmaps (CoglContext *ctx,
- GLenum gl_target)
-{
- if (ctx->driver == COGL_DRIVER_GLES2)
- GE( ctx, glGenerateMipmap (gl_target) );
-}
-
static CoglPixelFormat
_cogl_texture_driver_find_best_gl_get_data_format
(CoglContext *context,
@@ -588,6 +639,5 @@ _cogl_texture_driver_gles =
_cogl_texture_driver_size_supported_3d,
_cogl_texture_driver_try_setting_gl_border_color,
_cogl_texture_driver_allows_foreign_gl_target,
- _cogl_texture_driver_gl_generate_mipmaps,
_cogl_texture_driver_find_best_gl_get_data_format
};
diff --git a/cogl/driver/nop/cogl-texture-2d-nop-private.h b/cogl/driver/nop/cogl-texture-2d-nop-private.h
index 957a194..2e79e66 100644
--- a/cogl/driver/nop/cogl-texture-2d-nop-private.h
+++ b/cogl/driver/nop/cogl-texture-2d-nop-private.h
@@ -79,13 +79,14 @@ _cogl_texture_2d_nop_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
void
_cogl_texture_2d_nop_copy_from_framebuffer (CoglTexture2D *tex_2d,
- CoglFramebuffer *src_fb,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
- int height);
+ int height,
+ CoglFramebuffer *src_fb,
+ int dst_x,
+ int dst_y,
+ int level);
unsigned int
_cogl_texture_2d_nop_get_gl_handle (CoglTexture2D *tex_2d);
@@ -95,13 +96,14 @@ _cogl_texture_2d_nop_generate_mipmap (CoglTexture2D *tex_2d);
CoglBool
_cogl_texture_2d_nop_copy_from_bitmap (CoglTexture2D *tex_2d,
- CoglBitmap *bitmap,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
int height,
+ CoglBitmap *bitmap,
+ int dst_x,
+ int dst_y,
+ int level,
CoglError **error);
void
diff --git a/cogl/driver/nop/cogl-texture-2d-nop.c b/cogl/driver/nop/cogl-texture-2d-nop.c
index 5118e26..948d620 100644
--- a/cogl/driver/nop/cogl-texture-2d-nop.c
+++ b/cogl/driver/nop/cogl-texture-2d-nop.c
@@ -114,13 +114,14 @@ _cogl_texture_2d_nop_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
void
_cogl_texture_2d_nop_copy_from_framebuffer (CoglTexture2D *tex_2d,
- CoglFramebuffer *src_fb,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
- int height)
+ int height,
+ CoglFramebuffer *src_fb,
+ int dst_x,
+ int dst_y,
+ int level)
{
}
@@ -137,13 +138,14 @@ _cogl_texture_2d_nop_generate_mipmap (CoglTexture2D *tex_2d)
CoglBool
_cogl_texture_2d_nop_copy_from_bitmap (CoglTexture2D *tex_2d,
- CoglBitmap *bitmap,
- int dst_x,
- int dst_y,
int src_x,
int src_y,
int width,
int height,
+ CoglBitmap *bitmap,
+ int dst_x,
+ int dst_y,
+ int level,
CoglError **error)
{
return TRUE;
diff --git a/cogl/winsys/cogl-texture-pixmap-x11.c b/cogl/winsys/cogl-texture-pixmap-x11.c
index 4f64237..f5b3169 100644
--- a/cogl/winsys/cogl-texture-pixmap-x11.c
+++ b/cogl/winsys/cogl-texture-pixmap-x11.c
@@ -49,6 +49,7 @@
#include "cogl-xlib.h"
#include "cogl-error-private.h"
#include "cogl-texture-gl-private.h"
+#include "cogl-private.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -481,6 +482,8 @@ _cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap)
XImage *image;
int src_x, src_y;
int x, y, width, height;
+ int bpp;
+ int offset;
CoglError *ignore = NULL;
display = cogl_xlib_get_display ();
@@ -589,14 +592,17 @@ _cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap)
image->bits_per_pixel,
image->byte_order == LSBFirst);
+ bpp = _cogl_pixel_format_get_bytes_per_pixel (image_format);
+ offset = image->bytes_per_line * src_y + bpp * src_x;
+
cogl_texture_set_region (tex_pixmap->tex,
- src_x, src_y,
- x, y, width, height,
- image->width,
- image->height,
+ width,
+ height,
image_format,
image->bytes_per_line,
- (const uint8_t *) image->data,
+ ((const uint8_t *) image->data) + offset,
+ x, y,
+ 0, /* level */
&ignore);
/* If we have a shared memory segment then the XImage would be a
@@ -690,6 +696,7 @@ _cogl_texture_pixmap_x11_set_region (CoglTexture *tex,
int dst_y,
int dst_width,
int dst_height,
+ int level,
CoglBitmap *bmp,
CoglError **error)
{
diff --git a/tests/conform/test-alpha-textures.c b/tests/conform/test-alpha-textures.c
index 1861536..659815c 100644
--- a/tests/conform/test-alpha-textures.c
+++ b/tests/conform/test-alpha-textures.c
@@ -64,13 +64,12 @@ test_alpha_textures (void)
create_pipeline (&tex2, &pipeline2);
cogl_texture_set_region (tex2,
- 0, 0, /* src_x/y */
- 1, 1, /* dst_x/y */
- 1, 1, /* dst_width / dst_height */
1, 1, /* width / height */
COGL_PIXEL_FORMAT_A_8,
1, /* rowstride */
replacement_data,
+ 1, 1, /* dst_x/y */
+ 0, /* level */
NULL); /* abort on error */
cogl_framebuffer_draw_rectangle (test_fb,
diff --git a/tests/conform/test-premult.c b/tests/conform/test-premult.c
index 32983b7..a960409 100644
--- a/tests/conform/test-premult.c
+++ b/tests/conform/test-premult.c
@@ -68,13 +68,12 @@ set_region (CoglTexture *tex,
guchar *tex_data = gen_tex_data (color);
cogl_texture_set_region (tex,
- 0, 0, /* src x, y */
- 0, 0, /* dst x, y */
- QUAD_WIDTH, QUAD_WIDTH, /* dst width, height */
- QUAD_WIDTH, QUAD_WIDTH, /* src width, height */
+ QUAD_WIDTH, QUAD_WIDTH, /* height */
format,
0, /* auto compute row stride */
tex_data,
+ 0, 0, /* dst x,y */
+ 0, /* level */
NULL); /* don't catch errors */
}
diff --git a/tests/conform/test-sub-texture.c b/tests/conform/test-sub-texture.c
index 0291afb..4f9448f 100644
--- a/tests/conform/test-sub-texture.c
+++ b/tests/conform/test-sub-texture.c
@@ -267,10 +267,14 @@ validate_result (TestState *state)
/* Update the center half of the sub texture */
texture_data = create_update_data ();
cogl_texture_set_region (COGL_TEXTURE (sub_texture),
- 0, 0, 32, 32, 64, 64, 256, 256,
- COGL_PIXEL_FORMAT_RGBA_8888_PRE, 256 * 4,
+ 64, 64,
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE,
+ 256 * 4,
texture_data,
+ 32, 32, /* dst x, y */
+ 0, /* level */
NULL); /* don't catch errors */
+
g_free (texture_data);
cogl_object_unref (sub_texture);
/* Get the texture data */
diff --git a/tests/conform/test-write-texture-formats.c b/tests/conform/test-write-texture-formats.c
index 80002f1..8745014 100644
--- a/tests/conform/test-write-texture-formats.c
+++ b/tests/conform/test-write-texture-formats.c
@@ -38,13 +38,12 @@ test_write_byte (CoglPixelFormat format,
CoglTexture *texture = test_utils_create_color_texture (test_ctx, 0);
cogl_texture_set_region (texture,
- 0, 0, /* src_x / src_y */
- 0, 0, /* dst_x / dst_y */
- 1, 1, /* dst_w / dst_h */
1, 1, /* width / height */
format,
1, /* rowstride */
&byte,
+ 0, 0, /* dst_x, dst_y */
+ 0, /* level */
NULL); /* don't catch errors */
test_color (texture, expected_pixel);
@@ -60,13 +59,12 @@ test_write_short (CoglPixelFormat format,
CoglTexture *texture = test_utils_create_color_texture (test_ctx, 0);
cogl_texture_set_region (texture,
- 0, 0, /* src_x / src_y */
- 0, 0, /* dst_x / dst_y */
- 1, 1, /* dst_w / dst_h */
1, 1, /* width / height */
format,
2, /* rowstride */
(uint8_t *) &value,
+ 0, 0, /* dst_x, dst_y */
+ 0, /* level */
NULL); /* don't catch errors */
test_color (texture, expected_pixel);
@@ -84,13 +82,12 @@ test_write_bytes (CoglPixelFormat format,
value = GUINT32_TO_BE (value);
cogl_texture_set_region (texture,
- 0, 0, /* src_x / src_y */
- 0, 0, /* dst_x / dst_y */
- 1, 1, /* dst_w / dst_h */
1, 1, /* width / height */
format,
4, /* rowstride */
(uint8_t *) &value,
+ 0, 0, /* dst_x, dst_y */
+ 0, /* level */
NULL); /* don't catch errors */
test_color (texture, expected_pixel);
@@ -124,13 +121,12 @@ test_write_int (CoglPixelFormat format,
va_end (ap);
cogl_texture_set_region (texture,
- 0, 0, /* src_x / src_y */
- 0, 0, /* dst_x / dst_y */
- 1, 1, /* dst_w / dst_h */
1, 1, /* width / height */
format,
4, /* rowstride */
(uint8_t *) &tex_data,
+ 0, 0, /* dst_x, dst_y */
+ 0, /* level */
NULL); /* don't catch errors */
test_color (texture, expected_pixel);
--
1.7.7.6
More information about the Cogl
mailing list