/* Copy a block of pixels from one surface to another. */ static void r300_resource_copy_region(struct pipe_context *pipe, struct pipe_resource *dst, unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, unsigned src_level, const struct pipe_box *src_box) { enum pipe_format old_format = dst->format; enum pipe_format new_format = old_format; boolean is_depth; if (!pipe->screen->is_format_supported(pipe->screen, old_format, src->target, src->nr_samples, PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW, 0) && util_format_is_plain(old_format)) { switch (util_format_get_blocksize(old_format)) { case 1: new_format = PIPE_FORMAT_I8_UNORM; break; case 2: new_format = PIPE_FORMAT_B4G4R4A4_UNORM; break; case 4: new_format = PIPE_FORMAT_B8G8R8A8_UNORM; break; case 8: new_format = PIPE_FORMAT_R16G16B16A16_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_short_name(old_format)); } } is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; if (is_depth) { r300_flush_depth_stencil(pipe, src, src_level, src_box->z); } if (old_format != new_format) { r300_texture_reinterpret_format(pipe->screen, dst, new_format); r300_texture_reinterpret_format(pipe->screen, src, new_format); } r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); if (old_format != new_format) { r300_texture_reinterpret_format(pipe->screen, dst, old_format); r300_texture_reinterpret_format(pipe->screen, src, old_format); } }
/* Copy a block of pixels from one surface to another. */ static void r300_resource_copy_region(struct pipe_context *pipe, struct pipe_resource *dst, unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, unsigned src_level, const struct pipe_box *src_box) { struct r300_context *r300 = r300_context(pipe); struct pipe_framebuffer_state *fb = (struct pipe_framebuffer_state*)r300->fb_state.state; struct pipe_resource old_src = *src; struct pipe_resource old_dst = *dst; struct pipe_resource new_src = old_src; struct pipe_resource new_dst = old_dst; const struct util_format_description *desc = util_format_description(dst->format); struct pipe_box box; /* Fallback for buffers. */ if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); return; } if (r300->zmask_in_use && !r300->locked_zbuffer) { if (fb->zsbuf->texture == src || fb->zsbuf->texture == dst) { r300_decompress_zmask(r300); } } /* Handle non-renderable plain formats. */ if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB || !pipe->screen->is_format_supported(pipe->screen, src->format, src->target, src->nr_samples, PIPE_BIND_SAMPLER_VIEW) || !pipe->screen->is_format_supported(pipe->screen, dst->format, dst->target, dst->nr_samples, PIPE_BIND_RENDER_TARGET))) { switch (util_format_get_blocksize(old_dst.format)) { case 1: new_dst.format = PIPE_FORMAT_I8_UNORM; break; case 2: new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM; break; case 4: new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM; break; case 8: new_dst.format = PIPE_FORMAT_R16G16B16A16_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_short_name(dst->format)); } new_src.format = new_dst.format; } /* Handle compressed formats. */ if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC || desc->layout == UTIL_FORMAT_LAYOUT_RGTC) { switch (util_format_get_blocksize(old_dst.format)) { case 8: /* 1 pixel = 4 bits, * we set 1 pixel = 2 bytes ===> 4 times larger pixels. */ new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM; break; case 16: /* 1 pixel = 8 bits, * we set 1 pixel = 4 bytes ===> 4 times larger pixels. */ new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM; break; } /* Since the pixels are 4 times larger, we must decrease * the image size and the coordinates 4 times. */ new_src.format = new_dst.format; new_dst.height0 = (new_dst.height0 + 3) / 4; new_src.height0 = (new_src.height0 + 3) / 4; dsty /= 4; box = *src_box; box.y /= 4; box.height = (box.height + 3) / 4; src_box = &box; } if (old_src.format != new_src.format) r300_resource_set_properties(pipe->screen, src, &new_src); if (old_dst.format != new_dst.format) r300_resource_set_properties(pipe->screen, dst, &new_dst); r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); if (old_src.format != new_src.format) r300_resource_set_properties(pipe->screen, src, &old_src); if (old_dst.format != new_dst.format) r300_resource_set_properties(pipe->screen, dst, &old_dst); }