diff options
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r-- | src/gallium/drivers/r300/r300_blit.c | 74 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 14 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.h | 4 |
3 files changed, 85 insertions, 7 deletions
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index faaf9523cb2..eb9b0beeb5a 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -22,6 +22,9 @@ #include "r300_blit.h" #include "r300_context.h" +#include "r300_texture.h" + +#include "util/u_format.h" static void r300_blitter_save_states(struct r300_context* r300) { @@ -86,13 +89,13 @@ void r300_clear(struct pipe_context* pipe, buffers, rgba, depth, stencil); } -/* Copy a block of pixels from one surface to another. */ -void r300_surface_copy(struct pipe_context* pipe, - struct pipe_surface* dst, - unsigned dstx, unsigned dsty, - struct pipe_surface* src, - unsigned srcx, unsigned srcy, - unsigned width, unsigned height) +/* Copy a block of pixels from one surface to another using HW. */ +static void r300_hw_copy(struct pipe_context* pipe, + struct pipe_surface* dst, + unsigned dstx, unsigned dsty, + struct pipe_surface* src, + unsigned srcx, unsigned srcy, + unsigned width, unsigned height) { struct r300_context* r300 = r300_context(pipe); @@ -114,6 +117,63 @@ void r300_surface_copy(struct pipe_context* pipe, dst, dstx, dsty, src, srcx, srcy, width, height, TRUE); } +/* Copy a block of pixels from one surface to another. */ +void r300_surface_copy(struct pipe_context* pipe, + struct pipe_surface* dst, + unsigned dstx, unsigned dsty, + struct pipe_surface* src, + unsigned srcx, unsigned srcy, + unsigned width, unsigned height) +{ + enum pipe_format old_format = dst->texture->format; + enum pipe_format new_format = old_format; + + assert(dst->texture->format == src->texture->format); + + if (!pipe->screen->is_format_supported(pipe->screen, + old_format, src->texture->target, + PIPE_TEXTURE_USAGE_RENDER_TARGET | + PIPE_TEXTURE_USAGE_SAMPLER, 0)) { + switch (util_format_get_blocksize(old_format)) { + case 1: + new_format = PIPE_FORMAT_I8_UNORM; + break; + case 2: + new_format = PIPE_FORMAT_A4R4G4B4_UNORM; + break; + case 4: + new_format = PIPE_FORMAT_A8R8G8B8_UNORM; + break; + default: + debug_printf("r300: surface_copy: Unhandled format: %s. Falling back to software.\n" + "r300: surface_copy: Software fallback doesn't work for tiled textures.\n", + util_format_name(old_format)); + } + } + + if (old_format != new_format) { + dst->format = new_format; + src->format = new_format; + + r300_texture_reinterpret_format(pipe->screen, + dst->texture, new_format); + r300_texture_reinterpret_format(pipe->screen, + src->texture, new_format); + } + + r300_hw_copy(pipe, dst, dstx, dsty, src, srcx, srcy, width, height); + + if (old_format != new_format) { + dst->format = old_format; + src->format = old_format; + + r300_texture_reinterpret_format(pipe->screen, + dst->texture, old_format); + r300_texture_reinterpret_format(pipe->screen, + src->texture, old_format); + } +} + /* Fill a region of a surface with a constant value. */ void r300_surface_fill(struct pipe_context* pipe, struct pipe_surface* dst, diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index f228220bb54..f3325be87ae 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -85,6 +85,20 @@ static void r300_setup_texture_state(struct r300_screen* screen, struct r300_tex pt->width0, pt->height0, pt->last_level); } +void r300_texture_reinterpret_format(struct pipe_screen *screen, + struct pipe_texture *tex, + enum pipe_format new_format) +{ + struct r300_screen *r300screen = r300_screen(screen); + + SCREEN_DBG(r300screen, DBG_TEX, "r300: Reinterpreting format: %s -> %s\n", + util_format_name(tex->format), util_format_name(new_format)); + + tex->format = new_format; + + r300_setup_texture_state(r300_screen(screen), (struct r300_texture*)tex); +} + unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, unsigned zslice, unsigned face) { diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 1d2382da06d..b9c3ab80932 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -38,6 +38,10 @@ unsigned r300_texture_get_stride(struct r300_screen* screen, unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, unsigned zslice, unsigned face); +void r300_texture_reinterpret_format(struct pipe_screen *screen, + struct pipe_texture *tex, + enum pipe_format new_format); + /* Translate a pipe_format into a useful texture format for sampling. * * R300_EASY_TX_FORMAT swizzles the texture. |