diff --git a/src/mesa/drivers/dri/radeon/radeon_blit.c b/src/mesa/drivers/dri/radeon/radeon_blit.c index 1ccfa4e..208ce1b 100644 --- a/src/mesa/drivers/dri/radeon/radeon_blit.c +++ b/src/mesa/drivers/dri/radeon/radeon_blit.c @@ -396,3 +396,127 @@ GLboolean r100_blit(struct r100_context *r100, return GL_TRUE; } + + +GLboolean radeon_blit(struct r100_context *r100, + struct radeon_bo *src_bo, + intptr_t src_offset, + gl_format src_mesaformat, + 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_x_offset, + unsigned dst_y_offset, + unsigned reg_width, + unsigned reg_height, + unsigned flip_y) +{ + uint32_t src_bpp = _mesa_get_format_bytes(src_mesaformat); + uint32_t dst_bpp = _mesa_get_format_bytes(dst_mesaformat); + + if (is_blit_supported(dst_mesaformat)) + return r100_blit(r100, src_bo, src_offset, src_mesaformat, src_pitch, + src_width, src_height, src_x_offset, src_y_offset, + dst_bo, dst_offset, dst_mesaformat, dst_pitch, + dst_width, dst_height, dst_x_offset, dst_y_offset, + reg_width, reg_height, flip_y); + + /* Make sure that colorbuffer has even width - hw limitation */ + if (dst_pitch % 2 > 0) + ++dst_pitch; + + /* Rendering to small buffer doesn't work. + * Looks like a hw limitation. + */ + if (dst_pitch < 32) + return GL_FALSE; + + if (src_bo == dst_bo) { + return GL_FALSE; + } + + if (0) { + fprintf(stderr, "src: size [%d x %d], pitch %d, " + "offset [%d x %d], format %s, bo %p\n", + src_width, src_height, src_pitch, + src_x_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 (src_bpp != dst_bpp) + return GL_FALSE; + + switch (src_bpp) { + case 1: + src_mesaformat = MESA_FORMAT_A8; + break; + case 2: + src_mesaformat = MESA_FORMAT_RGB565; + break; + case 3: + src_mesaformat = MESA_FORMAT_A8; + src_width *= 3; + src_x_offset *= 3; + break; + case 4: + src_mesaformat = MESA_FORMAT_ARGB8888; + break; + default: + return GL_FALSE; + } + + switch (dst_bpp) { + case 1: + dst_mesaformat = MESA_FORMAT_A8; + break; + case 2: + dst_mesaformat = MESA_FORMAT_RGB565; + break; + case 3: + dst_mesaformat = MESA_FORMAT_A8; + dst_width *= 3; + dst_x_offset *= 3; + reg_width *= 3; + break; + case 4: + dst_mesaformat = MESA_FORMAT_ARGB8888; + break; + default: + return GL_FALSE; + } + + if ((src_width > 2047) || (dst_width > 2047)) + return GL_FALSE; + + /* 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. + */ + 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; + + return r100_blit(r100, src_bo, src_offset, src_mesaformat, src_pitch, + src_width, src_height, src_x_offset, src_y_offset, + dst_bo, dst_offset, dst_mesaformat, dst_pitch, + dst_width, dst_height, dst_x_offset, dst_y_offset, + reg_width, reg_height, flip_y); +}