Bug 1196 - Texture border drawing problems
* clutter/cogl/gl/cogl-texture.c (_cogl_texture_upload_subregion_to_gl) (_cogl_texture_upload_to_gl): * clutter/cogl/gles/cogl-texture.c (_cogl_texture_upload_to_gl) (_cogl_texture_upload_subregion_to_gl): When uploading data to a sliced texture, fill the waste pixels with copies of the edge of the real texture data. Otherwise the value of the waste pixels are undefined so it will show artifacts when the texture is scaled with GL_LINEAR and the pixels are blended in.
This commit is contained in:
parent
73b6bd2f17
commit
e43b7ddd3d
16
ChangeLog
16
ChangeLog
@ -1,3 +1,19 @@
|
|||||||
|
2008-10-27 Neil Roberts <neil@linux.intel.com>
|
||||||
|
|
||||||
|
Bug 1196 - Texture border drawing problems
|
||||||
|
|
||||||
|
* clutter/cogl/gl/cogl-texture.c (_cogl_texture_upload_subregion_to_gl)
|
||||||
|
(_cogl_texture_upload_to_gl):
|
||||||
|
|
||||||
|
* clutter/cogl/gles/cogl-texture.c (_cogl_texture_upload_to_gl)
|
||||||
|
(_cogl_texture_upload_subregion_to_gl):
|
||||||
|
|
||||||
|
When uploading data to a sliced texture, fill the waste pixels
|
||||||
|
with copies of the edge of the real texture data. Otherwise the
|
||||||
|
value of the waste pixels are undefined so it will show artifacts
|
||||||
|
when the texture is scaled with GL_LINEAR and the pixels are
|
||||||
|
blended in.
|
||||||
|
|
||||||
2008-10-22 Thomas Wood <thomas@linux.intel.com>
|
2008-10-22 Thomas Wood <thomas@linux.intel.com>
|
||||||
|
|
||||||
* tests/test-actors.c: Don't adjust the radius based on the number of
|
* tests/test-actors.c: Don't adjust the radius based on the number of
|
||||||
|
@ -212,6 +212,35 @@ _cogl_subregion_gl_store_rules (gint bmp_rowstride,
|
|||||||
GE( glPixelStorei (SKIP_PIXELS, src_x) );
|
GE( glPixelStorei (SKIP_PIXELS, src_x) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guchar *
|
||||||
|
_cogl_texture_allocate_waste_buffer (CoglTexture *tex)
|
||||||
|
{
|
||||||
|
CoglTexSliceSpan *last_x_span;
|
||||||
|
CoglTexSliceSpan *last_y_span;
|
||||||
|
guchar *waste_buf = NULL;
|
||||||
|
|
||||||
|
/* If the texture has any waste then allocate a buffer big enough to
|
||||||
|
fill the gaps */
|
||||||
|
last_x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan,
|
||||||
|
tex->slice_x_spans->len - 1);
|
||||||
|
last_y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan,
|
||||||
|
tex->slice_y_spans->len - 1);
|
||||||
|
if (last_x_span->waste > 0 || last_y_span->waste > 0)
|
||||||
|
{
|
||||||
|
gint bpp = _cogl_get_format_bpp (tex->bitmap.format);
|
||||||
|
CoglTexSliceSpan *first_x_span
|
||||||
|
= &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0);
|
||||||
|
CoglTexSliceSpan *first_y_span
|
||||||
|
= &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0);
|
||||||
|
guint right_size = first_y_span->size * last_x_span->waste;
|
||||||
|
guint bottom_size = first_x_span->size * last_y_span->waste;
|
||||||
|
|
||||||
|
waste_buf = g_malloc (MAX (right_size, bottom_size) * bpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return waste_buf;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_cogl_texture_upload_to_gl (CoglTexture *tex)
|
_cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||||
{
|
{
|
||||||
@ -220,9 +249,12 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
|||||||
GLuint gl_handle;
|
GLuint gl_handle;
|
||||||
gint bpp;
|
gint bpp;
|
||||||
gint x,y;
|
gint x,y;
|
||||||
|
guchar *waste_buf;
|
||||||
|
|
||||||
bpp = _cogl_get_format_bpp (tex->bitmap.format);
|
bpp = _cogl_get_format_bpp (tex->bitmap.format);
|
||||||
|
|
||||||
|
waste_buf = _cogl_texture_allocate_waste_buffer (tex);
|
||||||
|
|
||||||
/* Iterate vertical slices */
|
/* Iterate vertical slices */
|
||||||
for (y = 0; y < tex->slice_y_spans->len; ++y)
|
for (y = 0; y < tex->slice_y_spans->len; ++y)
|
||||||
{
|
{
|
||||||
@ -253,9 +285,78 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
|||||||
y_span->size - y_span->waste,
|
y_span->size - y_span->waste,
|
||||||
tex->gl_format, tex->gl_type,
|
tex->gl_format, tex->gl_type,
|
||||||
tex->bitmap.data) );
|
tex->bitmap.data) );
|
||||||
|
|
||||||
|
/* Fill the waste with a copies of the rightmost pixels */
|
||||||
|
if (x_span->waste > 0)
|
||||||
|
{
|
||||||
|
const guchar *src = tex->bitmap.data
|
||||||
|
+ y_span->start * tex->bitmap.rowstride
|
||||||
|
+ (x_span->start + x_span->size - x_span->waste - 1) * bpp;
|
||||||
|
guchar *dst = waste_buf;
|
||||||
|
guint wx, wy;
|
||||||
|
|
||||||
|
for (wy = 0; wy < y_span->size - y_span->waste; wy++)
|
||||||
|
{
|
||||||
|
for (wx = 0; wx < x_span->waste; wx++)
|
||||||
|
{
|
||||||
|
memcpy (dst, src, bpp);
|
||||||
|
dst += bpp;
|
||||||
|
}
|
||||||
|
src += tex->bitmap.rowstride;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cogl_subregion_gl_store_rules (x_span->waste * bpp,
|
||||||
|
x_span->waste,
|
||||||
|
bpp,
|
||||||
|
0, 0, FALSE);
|
||||||
|
|
||||||
|
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||||
|
x_span->size - x_span->waste, 0,
|
||||||
|
x_span->waste,
|
||||||
|
y_span->size - y_span->waste,
|
||||||
|
tex->gl_format, tex->gl_type,
|
||||||
|
waste_buf) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y_span->waste > 0)
|
||||||
|
{
|
||||||
|
const guchar *src = tex->bitmap.data
|
||||||
|
+ ((y_span->start + y_span->size - y_span->waste - 1)
|
||||||
|
* tex->bitmap.rowstride)
|
||||||
|
+ x_span->start * bpp;
|
||||||
|
guchar *dst = waste_buf;
|
||||||
|
guint wy, wx;
|
||||||
|
|
||||||
|
for (wy = 0; wy < y_span->waste; wy++)
|
||||||
|
{
|
||||||
|
memcpy (dst, src, (x_span->size - x_span->waste) * bpp);
|
||||||
|
dst += (x_span->size - x_span->waste) * bpp;
|
||||||
|
|
||||||
|
for (wx = 0; wx < x_span->waste; wx++)
|
||||||
|
{
|
||||||
|
memcpy (dst, dst - bpp, bpp);
|
||||||
|
dst += bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_cogl_subregion_gl_store_rules (x_span->size * bpp,
|
||||||
|
x_span->size,
|
||||||
|
bpp,
|
||||||
|
0, 0, FALSE);
|
||||||
|
|
||||||
|
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||||
|
0, y_span->size - y_span->waste,
|
||||||
|
x_span->size,
|
||||||
|
y_span->waste,
|
||||||
|
tex->gl_format, tex->gl_type,
|
||||||
|
waste_buf) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (waste_buf)
|
||||||
|
g_free (waste_buf);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,16 +475,21 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
|||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
GLuint source_gl_type)
|
GLuint source_gl_type)
|
||||||
{
|
{
|
||||||
gint bpp;
|
CoglTexSliceSpan *x_span;
|
||||||
CoglSpanIter x_iter;
|
CoglTexSliceSpan *y_span;
|
||||||
CoglSpanIter y_iter;
|
gint bpp;
|
||||||
GLuint gl_handle;
|
CoglSpanIter x_iter;
|
||||||
gint source_x = 0, source_y = 0;
|
CoglSpanIter y_iter;
|
||||||
gint inter_w = 0, inter_h = 0;
|
GLuint gl_handle;
|
||||||
gint local_x = 0, local_y = 0;
|
gint source_x = 0, source_y = 0;
|
||||||
|
gint inter_w = 0, inter_h = 0;
|
||||||
|
gint local_x = 0, local_y = 0;
|
||||||
|
guchar *waste_buf;
|
||||||
|
|
||||||
bpp = _cogl_get_format_bpp (source_bmp->format);
|
bpp = _cogl_get_format_bpp (source_bmp->format);
|
||||||
|
|
||||||
|
waste_buf = _cogl_texture_allocate_waste_buffer (tex);
|
||||||
|
|
||||||
/* Iterate vertical spans */
|
/* Iterate vertical spans */
|
||||||
for (source_y = src_y,
|
for (source_y = src_y,
|
||||||
_cogl_span_iter_begin (&y_iter, tex->slice_y_spans,
|
_cogl_span_iter_begin (&y_iter, tex->slice_y_spans,
|
||||||
@ -402,6 +508,9 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan,
|
||||||
|
y_iter.index);
|
||||||
|
|
||||||
/* Iterate horizontal spans */
|
/* Iterate horizontal spans */
|
||||||
for (source_x = src_x,
|
for (source_x = src_x,
|
||||||
_cogl_span_iter_begin (&x_iter, tex->slice_x_spans,
|
_cogl_span_iter_begin (&x_iter, tex->slice_x_spans,
|
||||||
@ -420,6 +529,9 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan,
|
||||||
|
x_iter.index);
|
||||||
|
|
||||||
/* Pick intersection width and height */
|
/* Pick intersection width and height */
|
||||||
inter_w = CLUTTER_FIXED_TO_INT (x_iter.intersect_end -
|
inter_w = CLUTTER_FIXED_TO_INT (x_iter.intersect_end -
|
||||||
x_iter.intersect_start);
|
x_iter.intersect_start);
|
||||||
@ -455,9 +567,96 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
|||||||
source_gl_format,
|
source_gl_format,
|
||||||
source_gl_type,
|
source_gl_type,
|
||||||
source_bmp->data) );
|
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 */
|
||||||
|
if (x_span->waste > 0
|
||||||
|
&& local_x < x_span->size - x_span->waste
|
||||||
|
&& local_x + inter_w >= x_span->size - x_span->waste)
|
||||||
|
{
|
||||||
|
const guchar *src = source_bmp->data
|
||||||
|
+ (src_y + CLUTTER_FIXED_TO_INT (y_iter.intersect_start)
|
||||||
|
- dst_y) * source_bmp->rowstride
|
||||||
|
+ (src_x + x_span->start + x_span->size - x_span->waste
|
||||||
|
- dst_x - 1) * bpp;
|
||||||
|
guchar *dst = waste_buf;
|
||||||
|
guint wx, wy;
|
||||||
|
|
||||||
|
for (wy = 0; wy < inter_h; wy++)
|
||||||
|
{
|
||||||
|
for (wx = 0; wx < x_span->waste; wx++)
|
||||||
|
{
|
||||||
|
memcpy (dst, src, bpp);
|
||||||
|
dst += bpp;
|
||||||
|
}
|
||||||
|
src += source_bmp->rowstride;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cogl_subregion_gl_store_rules (x_span->waste * bpp,
|
||||||
|
x_span->waste,
|
||||||
|
bpp,
|
||||||
|
0, 0, FALSE);
|
||||||
|
|
||||||
|
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||||
|
x_span->size - x_span->waste, local_y,
|
||||||
|
x_span->waste,
|
||||||
|
inter_h,
|
||||||
|
source_gl_format,
|
||||||
|
source_gl_type,
|
||||||
|
waste_buf) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* same for the bottom-most pixels */
|
||||||
|
if (y_span->waste > 0
|
||||||
|
&& local_y < y_span->size - y_span->waste
|
||||||
|
&& local_y + inter_h >= y_span->size - y_span->waste)
|
||||||
|
{
|
||||||
|
const guchar *src = source_bmp->data
|
||||||
|
+ (src_x + CLUTTER_FIXED_TO_INT (x_iter.intersect_start)
|
||||||
|
- dst_x) * bpp
|
||||||
|
+ (src_y + y_span->start + y_span->size - y_span->waste
|
||||||
|
- dst_y - 1) * source_bmp->rowstride;
|
||||||
|
guchar *dst = waste_buf;
|
||||||
|
guint wy, wx;
|
||||||
|
guint copy_width;
|
||||||
|
|
||||||
|
if (local_x + inter_w >= x_span->size - x_span->waste)
|
||||||
|
copy_width = x_span->size - local_x;
|
||||||
|
else
|
||||||
|
copy_width = inter_w;
|
||||||
|
|
||||||
|
for (wy = 0; wy < y_span->waste; wy++)
|
||||||
|
{
|
||||||
|
memcpy (dst, src, inter_w * bpp);
|
||||||
|
dst += inter_w * bpp;
|
||||||
|
|
||||||
|
for (wx = inter_w; wx < copy_width; wx++)
|
||||||
|
{
|
||||||
|
memcpy (dst, dst - bpp, bpp);
|
||||||
|
dst += bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_cogl_subregion_gl_store_rules (copy_width * bpp,
|
||||||
|
copy_width,
|
||||||
|
bpp,
|
||||||
|
0, 0, FALSE);
|
||||||
|
|
||||||
|
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||||
|
local_x, y_span->size - y_span->waste,
|
||||||
|
copy_width,
|
||||||
|
y_span->waste,
|
||||||
|
source_gl_format,
|
||||||
|
source_gl_type,
|
||||||
|
waste_buf) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (waste_buf)
|
||||||
|
g_free (waste_buf);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +174,35 @@ _cogl_span_iter_end (CoglSpanIter *iter)
|
|||||||
return iter->pos >= iter->cover_end;
|
return iter->pos >= iter->cover_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guchar *
|
||||||
|
_cogl_texture_allocate_waste_buffer (CoglTexture *tex)
|
||||||
|
{
|
||||||
|
CoglTexSliceSpan *last_x_span;
|
||||||
|
CoglTexSliceSpan *last_y_span;
|
||||||
|
guchar *waste_buf = NULL;
|
||||||
|
|
||||||
|
/* If the texture has any waste then allocate a buffer big enough to
|
||||||
|
fill the gaps */
|
||||||
|
last_x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan,
|
||||||
|
tex->slice_x_spans->len - 1);
|
||||||
|
last_y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan,
|
||||||
|
tex->slice_y_spans->len - 1);
|
||||||
|
if (last_x_span->waste > 0 || last_y_span->waste > 0)
|
||||||
|
{
|
||||||
|
gint bpp = _cogl_get_format_bpp (tex->bitmap.format);
|
||||||
|
CoglTexSliceSpan *first_x_span
|
||||||
|
= &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0);
|
||||||
|
CoglTexSliceSpan *first_y_span
|
||||||
|
= &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0);
|
||||||
|
guint right_size = first_y_span->size * last_x_span->waste;
|
||||||
|
guint bottom_size = first_x_span->size * last_y_span->waste;
|
||||||
|
|
||||||
|
waste_buf = g_malloc (MAX (right_size, bottom_size) * bpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return waste_buf;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_cogl_texture_upload_to_gl (CoglTexture *tex)
|
_cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||||
{
|
{
|
||||||
@ -182,6 +211,7 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
|||||||
GLuint gl_handle;
|
GLuint gl_handle;
|
||||||
gint bpp;
|
gint bpp;
|
||||||
gint x,y;
|
gint x,y;
|
||||||
|
guchar *waste_buf;
|
||||||
CoglBitmap slice_bmp;
|
CoglBitmap slice_bmp;
|
||||||
|
|
||||||
/* FIXME: might optimize by not copying to intermediate slice
|
/* FIXME: might optimize by not copying to intermediate slice
|
||||||
@ -190,6 +220,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
|||||||
|
|
||||||
bpp = _cogl_get_format_bpp (tex->bitmap.format);
|
bpp = _cogl_get_format_bpp (tex->bitmap.format);
|
||||||
|
|
||||||
|
waste_buf = _cogl_texture_allocate_waste_buffer (tex);
|
||||||
|
|
||||||
/* Iterate vertical slices */
|
/* Iterate vertical slices */
|
||||||
for (y = 0; y < tex->slice_y_spans->len; ++y)
|
for (y = 0; y < tex->slice_y_spans->len; ++y)
|
||||||
{
|
{
|
||||||
@ -233,6 +265,62 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
|||||||
tex->gl_format, tex->gl_type,
|
tex->gl_format, tex->gl_type,
|
||||||
slice_bmp.data) );
|
slice_bmp.data) );
|
||||||
|
|
||||||
|
/* Fill the waste with a copies of the rightmost pixels */
|
||||||
|
if (x_span->waste > 0)
|
||||||
|
{
|
||||||
|
const guchar *src = tex->bitmap.data
|
||||||
|
+ y_span->start * tex->bitmap.rowstride
|
||||||
|
+ (x_span->start + x_span->size - x_span->waste - 1) * bpp;
|
||||||
|
guchar *dst = waste_buf;
|
||||||
|
guint wx, wy;
|
||||||
|
|
||||||
|
for (wy = 0; wy < y_span->size - y_span->waste; wy++)
|
||||||
|
{
|
||||||
|
for (wx = 0; wx < x_span->waste; wx++)
|
||||||
|
{
|
||||||
|
memcpy (dst, src, bpp);
|
||||||
|
dst += bpp;
|
||||||
|
}
|
||||||
|
src += tex->bitmap.rowstride;
|
||||||
|
}
|
||||||
|
|
||||||
|
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||||
|
x_span->size - x_span->waste, 0,
|
||||||
|
x_span->waste,
|
||||||
|
y_span->size - y_span->waste,
|
||||||
|
tex->gl_format, tex->gl_type,
|
||||||
|
waste_buf) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y_span->waste > 0)
|
||||||
|
{
|
||||||
|
const guchar *src = tex->bitmap.data
|
||||||
|
+ ((y_span->start + y_span->size - y_span->waste - 1)
|
||||||
|
* tex->bitmap.rowstride)
|
||||||
|
+ x_span->start * bpp;
|
||||||
|
guchar *dst = waste_buf;
|
||||||
|
guint wy, wx;
|
||||||
|
|
||||||
|
for (wy = 0; wy < y_span->waste; wy++)
|
||||||
|
{
|
||||||
|
memcpy (dst, src, (x_span->size - x_span->waste) * bpp);
|
||||||
|
dst += (x_span->size - x_span->waste) * bpp;
|
||||||
|
|
||||||
|
for (wx = 0; wx < x_span->waste; wx++)
|
||||||
|
{
|
||||||
|
memcpy (dst, dst - bpp, bpp);
|
||||||
|
dst += bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||||
|
0, y_span->size - y_span->waste,
|
||||||
|
x_span->size,
|
||||||
|
y_span->waste,
|
||||||
|
tex->gl_format, tex->gl_type,
|
||||||
|
waste_buf) );
|
||||||
|
}
|
||||||
|
|
||||||
if (tex->auto_mipmap)
|
if (tex->auto_mipmap)
|
||||||
cogl_wrap_glGenerateMipmap (tex->gl_target);
|
cogl_wrap_glGenerateMipmap (tex->gl_target);
|
||||||
|
|
||||||
@ -241,6 +329,9 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (waste_buf)
|
||||||
|
g_free (waste_buf);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,17 +585,22 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
|||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
GLuint source_gl_type)
|
GLuint source_gl_type)
|
||||||
{
|
{
|
||||||
gint bpp;
|
CoglTexSliceSpan *x_span;
|
||||||
CoglSpanIter x_iter;
|
CoglTexSliceSpan *y_span;
|
||||||
CoglSpanIter y_iter;
|
gint bpp;
|
||||||
GLuint gl_handle;
|
CoglSpanIter x_iter;
|
||||||
gint source_x = 0, source_y = 0;
|
CoglSpanIter y_iter;
|
||||||
gint inter_w = 0, inter_h = 0;
|
GLuint gl_handle;
|
||||||
gint local_x = 0, local_y = 0;
|
gint source_x = 0, source_y = 0;
|
||||||
CoglBitmap slice_bmp;
|
gint inter_w = 0, inter_h = 0;
|
||||||
|
gint local_x = 0, local_y = 0;
|
||||||
|
guchar *waste_buf;
|
||||||
|
CoglBitmap slice_bmp;
|
||||||
|
|
||||||
bpp = _cogl_get_format_bpp (source_bmp->format);
|
bpp = _cogl_get_format_bpp (source_bmp->format);
|
||||||
|
|
||||||
|
waste_buf = _cogl_texture_allocate_waste_buffer (tex);
|
||||||
|
|
||||||
/* FIXME: might optimize by not copying to intermediate slice
|
/* FIXME: might optimize by not copying to intermediate slice
|
||||||
bitmap when source rowstride = bpp * width and the texture
|
bitmap when source rowstride = bpp * width and the texture
|
||||||
image is not sliced */
|
image is not sliced */
|
||||||
@ -527,6 +623,9 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan,
|
||||||
|
y_iter.index);
|
||||||
|
|
||||||
/* Iterate horizontal spans */
|
/* Iterate horizontal spans */
|
||||||
for (source_x = src_x,
|
for (source_x = src_x,
|
||||||
_cogl_span_iter_begin (&x_iter, tex->slice_x_spans,
|
_cogl_span_iter_begin (&x_iter, tex->slice_x_spans,
|
||||||
@ -545,6 +644,9 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan,
|
||||||
|
x_iter.index);
|
||||||
|
|
||||||
/* Pick intersection width and height */
|
/* Pick intersection width and height */
|
||||||
inter_w = CLUTTER_FIXED_TO_INT (x_iter.intersect_end -
|
inter_w = CLUTTER_FIXED_TO_INT (x_iter.intersect_end -
|
||||||
x_iter.intersect_start);
|
x_iter.intersect_start);
|
||||||
@ -592,6 +694,80 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
|||||||
source_gl_type,
|
source_gl_type,
|
||||||
slice_bmp.data) );
|
slice_bmp.data) );
|
||||||
|
|
||||||
|
/* If the x_span is sliced and the upload touches the
|
||||||
|
rightmost pixels then fill the waste with copies of the
|
||||||
|
pixels */
|
||||||
|
if (x_span->waste > 0
|
||||||
|
&& local_x < x_span->size - x_span->waste
|
||||||
|
&& local_x + inter_w >= x_span->size - x_span->waste)
|
||||||
|
{
|
||||||
|
const guchar *src = source_bmp->data
|
||||||
|
+ (src_y + CLUTTER_FIXED_TO_INT (y_iter.intersect_start)
|
||||||
|
- dst_y) * source_bmp->rowstride
|
||||||
|
+ (src_x + x_span->start + x_span->size - x_span->waste
|
||||||
|
- dst_x - 1) * bpp;
|
||||||
|
guchar *dst = waste_buf;
|
||||||
|
guint wx, wy;
|
||||||
|
|
||||||
|
for (wy = 0; wy < inter_h; wy++)
|
||||||
|
{
|
||||||
|
for (wx = 0; wx < x_span->waste; wx++)
|
||||||
|
{
|
||||||
|
memcpy (dst, src, bpp);
|
||||||
|
dst += bpp;
|
||||||
|
}
|
||||||
|
src += source_bmp->rowstride;
|
||||||
|
}
|
||||||
|
|
||||||
|
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||||
|
x_span->size - x_span->waste, local_y,
|
||||||
|
x_span->waste,
|
||||||
|
inter_h,
|
||||||
|
source_gl_format,
|
||||||
|
source_gl_type,
|
||||||
|
waste_buf) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* same for the bottom-most pixels */
|
||||||
|
if (y_span->waste > 0
|
||||||
|
&& local_y < y_span->size - y_span->waste
|
||||||
|
&& local_y + inter_h >= y_span->size - y_span->waste)
|
||||||
|
{
|
||||||
|
const guchar *src = source_bmp->data
|
||||||
|
+ (src_x + CLUTTER_FIXED_TO_INT (x_iter.intersect_start)
|
||||||
|
- dst_x) * bpp
|
||||||
|
+ (src_y + y_span->start + y_span->size - y_span->waste
|
||||||
|
- dst_y - 1) * source_bmp->rowstride;
|
||||||
|
guchar *dst = waste_buf;
|
||||||
|
guint wy, wx;
|
||||||
|
guint copy_width;
|
||||||
|
|
||||||
|
if (local_x + inter_w >= x_span->size - x_span->waste)
|
||||||
|
copy_width = x_span->size - local_x;
|
||||||
|
else
|
||||||
|
copy_width = inter_w;
|
||||||
|
|
||||||
|
for (wy = 0; wy < y_span->waste; wy++)
|
||||||
|
{
|
||||||
|
memcpy (dst, src, inter_w * bpp);
|
||||||
|
dst += inter_w * bpp;
|
||||||
|
|
||||||
|
for (wx = inter_w; wx < copy_width; wx++)
|
||||||
|
{
|
||||||
|
memcpy (dst, dst - bpp, bpp);
|
||||||
|
dst += bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GE( glTexSubImage2D (tex->gl_target, 0,
|
||||||
|
local_x, y_span->size - y_span->waste,
|
||||||
|
copy_width,
|
||||||
|
y_span->waste,
|
||||||
|
source_gl_format,
|
||||||
|
source_gl_type,
|
||||||
|
waste_buf) );
|
||||||
|
}
|
||||||
|
|
||||||
if (tex->auto_mipmap)
|
if (tex->auto_mipmap)
|
||||||
cogl_wrap_glGenerateMipmap (tex->gl_target);
|
cogl_wrap_glGenerateMipmap (tex->gl_target);
|
||||||
|
|
||||||
@ -600,6 +776,9 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (waste_buf)
|
||||||
|
g_free (waste_buf);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user