From 4b6dee08652706d02939844fe209cddbae8966e4 Mon Sep 17 00:00:00 2001 From: Maciej Cencora Date: Sat, 19 Dec 2009 14:25:53 +0100 Subject: r300: minor blit rework Use vert/tex coords instead of byte offsets for specyfing src/dst image offsets. This will allow for blitting between tiled/untiled buffers. --- src/mesa/drivers/dri/r300/r300_blit.c | 115 ++++++++++++++++++++++++++----- src/mesa/drivers/dri/r300/r300_blit.h | 9 ++- src/mesa/drivers/dri/r300/r300_texcopy.c | 12 ++-- 3 files changed, 113 insertions(+), 23 deletions(-) diff --git a/src/mesa/drivers/dri/r300/r300_blit.c b/src/mesa/drivers/dri/r300/r300_blit.c index d03fbfa07d6..ea626d942dc 100644 --- a/src/mesa/drivers/dri/r300/r300_blit.c +++ b/src/mesa/drivers/dri/r300/r300_blit.c @@ -389,14 +389,49 @@ static GLboolean validate_buffers(struct r300_context *r300, return GL_TRUE; } +/** + * Calculate texcoords for given image region. + * Output values are [minx, maxx, miny, maxy] + */ +static void calc_tex_coords(float img_width, float img_height, + float x, float y, + float reg_width, float reg_height, + unsigned flip_y, float *buf) +{ + buf[0] = x / img_width; + buf[1] = buf[0] + reg_width / img_width; + buf[2] = y / img_height; + buf[3] = buf[2] + reg_height / img_height; + if (flip_y) + { + float tmp = buf[2]; + buf[2] = 1.0 - buf[3]; + buf[3] = 1.0 - tmp; + } +} + static void emit_draw_packet(struct r300_context *r300, - float src_width, float src_height, - float dst_width, float dst_height) + unsigned src_width, unsigned src_height, + unsigned src_x_offset, unsigned src_y_offset, + unsigned dst_x_offset, unsigned dst_y_offset, + unsigned reg_width, unsigned reg_height, + unsigned flip_y) { - float verts[] = { 0.0, 0.0, 0.0, 1.0, - 0.0, dst_height, 0.0, 1.0 - dst_height/src_height, - dst_width, dst_height, dst_width/src_width, 1.0 - dst_height/src_height, - dst_width, 0.0, dst_width/src_width, 1.0 }; + float texcoords[4]; + + calc_tex_coords(src_width, src_height, + src_x_offset, src_y_offset, + reg_width, reg_height, + flip_y, texcoords); + + float verts[] = { dst_x_offset, dst_y_offset, + texcoords[0], texcoords[3], + dst_x_offset, dst_y_offset + reg_height, + texcoords[0], texcoords[2], + dst_x_offset + reg_width, dst_y_offset + reg_height, + texcoords[1], texcoords[2], + dst_x_offset + reg_width, dst_y_offset, + texcoords[1], texcoords[3] }; BATCH_LOCALS(&r300->radeon); @@ -461,6 +496,30 @@ static void emit_cb_setup(struct r300_context *r300, END_BATCH(); } +/** + * Copy a region of [@a width x @a height] pixels from source buffer + * to destination buffer. + * @param[in] r300 r300 context + * @param[in] src_bo source radeon buffer object + * @param[in] src_offset offset of the source image in the @a src_bo + * @param[in] src_mesaformat source image format + * @param[in] src_pitch aligned source image width + * @param[in] src_width source image width + * @param[in] src_height source image height + * @param[in] src_x_offset x offset in the source image + * @param[in] src_y_offset y offset in the source image + * @param[in] dst_bo destination radeon buffer object + * @param[in] dst_offset offset of the destination image in the @a dst_bo + * @param[in] dst_mesaformat destination image format + * @param[in] dst_pitch aligned destination image width + * @param[in] dst_width destination image width + * @param[in] dst_height destination image height + * @param[in] dst_x_offset x offset in the destination image + * @param[in] dst_y_offset y offset in the destination image + * @param[in] width region width + * @param[in] height region height + * @param[in] flip_y set if y coords of the source image need to be flipped + */ GLboolean r300_blit(struct r300_context *r300, struct radeon_bo *src_bo, intptr_t src_offset, @@ -468,30 +527,48 @@ GLboolean r300_blit(struct r300_context *r300, unsigned src_pitch, unsigned src_width, unsigned src_height, + unsigned src_x_offset, + unsigned src_y_offset, struct radeon_bo *dst_bo, intptr_t dst_offset, gl_format dst_mesaformat, unsigned dst_pitch, unsigned dst_width, - unsigned dst_height) + unsigned dst_height, + unsigned dst_x_offset, + unsigned dst_y_offset, + unsigned reg_width, + unsigned reg_height, + unsigned flip_y) { - /* Need to clamp the destination size to make sure - * we don't write outside of the buffer + /* Need to clamp the region size to make sure + * we don't read outside of the source buffer + * or write outside of the destination buffer. */ - dst_width = MIN2(dst_width, src_width); - dst_height = MIN2(src_height, dst_height); + if (reg_width + src_x_offset > src_width) + reg_width = src_width - src_x_offset; + if (reg_height + src_y_offset > src_height) + reg_height = src_height - src_y_offset; + if (reg_width + dst_x_offset > dst_width) + reg_width = dst_width - dst_x_offset; + if (reg_height + dst_y_offset > dst_height) + reg_height = dst_height - dst_y_offset; if (src_bo == dst_bo) { return GL_FALSE; } if (0) { - fprintf(stderr, "src: width %d, height %d, pitch %d, format %s\n", + fprintf(stderr, "src: size [%d x %d], pitch %d, " + "offset [%d x %d], format %s, bo %p\n", src_width, src_height, src_pitch, - _mesa_get_format_name(src_mesaformat)); - fprintf(stderr, "dst: width %d, height %d, pitch %d, format %s\n", - dst_width, dst_height, dst_pitch, - _mesa_get_format_name(dst_mesaformat)); + src_offset, src_y_offset, + _mesa_get_format_name(src_mesaformat), + src_bo); + fprintf(stderr, "dst: pitch %d, offset[%d x %d], format %s, bo %p\n", + dst_pitch, dst_x_offset, dst_y_offset, + _mesa_get_format_name(dst_mesaformat), dst_bo); + fprintf(stderr, "region: %d x %d\n", reg_width, reg_height); } if (!validate_buffers(r300, src_bo, dst_bo)) @@ -516,7 +593,11 @@ GLboolean r300_blit(struct r300_context *r300, emit_cb_setup(r300, dst_bo, dst_offset, dst_mesaformat, dst_pitch, dst_width, dst_height); - emit_draw_packet(r300, src_width, src_height, dst_width, dst_height); + emit_draw_packet(r300, src_width, src_height, + src_x_offset, src_y_offset, + dst_x_offset, dst_y_offset, + reg_width, reg_height, + flip_y); r300EmitCacheFlush(r300); diff --git a/src/mesa/drivers/dri/r300/r300_blit.h b/src/mesa/drivers/dri/r300/r300_blit.h index 28ffd4ea421..dc21e880982 100644 --- a/src/mesa/drivers/dri/r300/r300_blit.h +++ b/src/mesa/drivers/dri/r300/r300_blit.h @@ -37,11 +37,18 @@ GLboolean r300_blit(struct r300_context *r300, unsigned src_pitch, unsigned src_width, unsigned src_height, + unsigned src_x_offset, + unsigned src_y_offset, struct radeon_bo *dst_bo, intptr_t dst_offset, gl_format dst_mesaformat, unsigned dst_pitch, unsigned dst_width, - unsigned dst_height); + unsigned dst_height, + unsigned dst_x_offset, + unsigned dst_y_offset, + unsigned width, + unsigned height, + unsigned flip_y); #endif // R300_BLIT_H \ No newline at end of file diff --git a/src/mesa/drivers/dri/r300/r300_texcopy.c b/src/mesa/drivers/dri/r300/r300_texcopy.c index 893c8586f7e..ebc9c05b8a8 100644 --- a/src/mesa/drivers/dri/r300/r300_texcopy.c +++ b/src/mesa/drivers/dri/r300/r300_texcopy.c @@ -37,6 +37,8 @@ #include "r300_blit.h" #include
+// TODO: +// need to pass correct pitch for small dst textures! static GLboolean do_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, @@ -64,10 +66,8 @@ do_copy_texsubimage(GLcontext *ctx, assert(timg->base.Width >= dstx + width); assert(timg->base.Height >= dsty + height); - intptr_t src_offset = rrb->draw_offset + x * rrb->cpp + y * rrb->pitch; + intptr_t src_offset = rrb->draw_offset; intptr_t dst_offset = radeon_miptree_image_offset(timg->mt, _mesa_tex_target_to_face(target), level); - dst_offset += dstx * _mesa_get_format_bytes(timg->base.TexFormat) + - dsty * _mesa_format_row_stride(timg->base.TexFormat, timg->base.Width); if (src_offset % 32 || dst_offset % 32) { return GL_FALSE; @@ -85,8 +85,10 @@ do_copy_texsubimage(GLcontext *ctx, /* blit from src buffer to texture */ return r300_blit(r300, rrb->bo, src_offset, rrb->base.Format, rrb->pitch/rrb->cpp, - rrb->base.Width, rrb->base.Height, timg->mt->bo ? timg->mt->bo : timg->bo, dst_offset, - timg->base.TexFormat, timg->base.Width, width, height); + rrb->base.Width, rrb->base.Height, x, y, + timg->mt->bo, dst_offset, timg->base.TexFormat, + timg->base.Width, timg->base.Width, timg->base.Height, + dstx, dsty, width, height, 1); } static void -- cgit v1.2.3