/*
- * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Copyright 2009 Marek Olšák <maraeo@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "r300_blit.h"
+#include "r300_context.h"
+#include "r300_texture.h"
-/* Does a "paint" into the specified rectangle.
- * Returns 1 on success, 0 on error. */
-int r300_fill_blit(struct r300_context* r300,
- unsigned cpp,
- short dst_pitch,
- struct pipe_buffer* dst_buffer,
- unsigned dst_offset,
- short x, short y,
- short w, short h,
- unsigned color)
+#include "util/u_format.h"
+
+static void r300_blitter_save_states(struct r300_context* r300)
+{
+ util_blitter_save_blend(r300->blitter, r300->blend_state.state);
+ util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state.state);
+ util_blitter_save_stencil_ref(r300->blitter, &(r300->stencil_ref));
+ util_blitter_save_rasterizer(r300->blitter, r300->rs_state.state);
+ util_blitter_save_fragment_shader(r300->blitter, r300->fs.state);
+ util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state);
+ util_blitter_save_viewport(r300->blitter, &r300->viewport);
+ util_blitter_save_clip(r300->blitter, &r300->clip);
+ util_blitter_save_vertex_elements(r300->blitter, r300->velems);
+}
+
+/* Clear currently bound buffers. */
+void r300_clear(struct pipe_context* pipe,
+ unsigned buffers,
+ const float* rgba,
+ double depth,
+ unsigned stencil)
+{
+ /* XXX Implement fastfill.
+ *
+ * If fastfill is enabled, a few facts should be considered:
+ *
+ * 1) Zbuffer must be micro-tiled and whole microtiles must be
+ * written.
+ *
+ * 2) ZB_DEPTHCLEARVALUE is used to clear a zbuffer and Z Mask must be
+ * equal to 0.
+ *
+ * 3) RB3D_COLOR_CLEAR_VALUE is used to clear a colorbuffer and
+ * RB3D_COLOR_CHANNEL_MASK must be equal to 0.
+ *
+ * 4) ZB_CB_CLEAR can be used to make the ZB units help in clearing
+ * the colorbuffer. The color clear value is supplied through both
+ * RB3D_COLOR_CLEAR_VALUE and ZB_DEPTHCLEARVALUE, and the colorbuffer
+ * must be set in ZB_DEPTHOFFSET and ZB_DEPTHPITCH in addition to
+ * RB3D_COLOROFFSET and RB3D_COLORPITCH. It's obvious that the zbuffer
+ * will not be cleared and multiple render targets cannot be cleared
+ * this way either.
+ *
+ * 5) For 16-bit integer buffering, compression causes a hung with one or
+ * two samples and should not be used.
+ *
+ * 6) Fastfill must not be used if reading of compressed Z data is disabled
+ * and writing of compressed Z data is enabled (RD/WR_COMP_ENABLE),
+ * i.e. it cannot be used to compress the zbuffer.
+ * (what the hell does that mean and how does it fit in clearing
+ * the buffers?)
+ *
+ * - Marek
+ */
+
+ struct r300_context* r300 = r300_context(pipe);
+ struct pipe_framebuffer_state* fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+
+ r300_blitter_save_states(r300);
+
+ util_blitter_clear(r300->blitter,
+ fb->width,
+ fb->height,
+ fb->nr_cbufs,
+ buffers, rgba, depth, stencil);
+}
+
+/* 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);
+ struct r300_textures_state* state =
+ (struct r300_textures_state*)r300->textures_state.state;
+
+ /* Yeah we have to save all those states to ensure this blitter operation
+ * is really transparent. The states will be restored by the blitter once
+ * copying is done. */
+ r300_blitter_save_states(r300);
+ util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
+
+ util_blitter_save_fragment_sampler_states(
+ r300->blitter, state->sampler_state_count,
+ (void**)state->sampler_states);
+
+ util_blitter_save_fragment_sampler_views(
+ r300->blitter, state->sampler_view_count,
+ (struct pipe_sampler_view**)state->sampler_views);
+
+ /* Do a copy */
+ util_blitter_copy(r300->blitter,
+ 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)
{
- uint32_t dest_type;
-
- /* Check for fallbacks. */
- /* XXX we can do YUV surfaces, too, but only in 3D mode. Hmm... */
- switch(cpp) {
- case 2:
- case 6:
- dest_type = ATI_DATATYPE_CI8;
- break;
- case 4:
- dest_type = ATI_DATATYPE_RGB565;
- break;
- case 8:
- dest_type = ATI_DATATYPE_ARGB8888;
- break;
- default:
- /* Whatever this is, we can't fill it. (Yet.) */
- return 0;
+ 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_BIND_RENDER_TARGET |
+ PIPE_BIND_SAMPLER_VIEW, 0)) {
+ 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_name(old_format));
+ }
}
- /* XXX odds are *incredibly* good that we were in 3D just a bit ago,
- * so flush here first. */
-
- /* Set up the 2D engine. */
- OUT_CS_REG(RADEON_DEFAULT_SC_BOTTOM_RIGHT,
- RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX);
- OUT_CS_REG(RADEON_DP_GUI_MASTER_CNTL,
- RADEON_GMC_DST_PITCH_OFFSET_CNTL |
- RADEON_GMC_BRUSH_SOLID_COLOR |
- (dest_type << 8) |
- RADEON_GMC_SRC_DATATYPE_COLOR |
- RADEON_ROP3_P |
- RADEON_GMC_CLR_CMP_CNTL_DIS);
- /* XXX pack this? */
- OUT_CS_REG(RADEON_DP_BRUSH_FRGD_CLR, color);
- OUT_CS_REG(RADEON_DP_BRUSH_BKGD_CLR, 0x00000000);
- OUT_CS_REG(RADEON_DP_SRC_FRGD_CLR, 0xffffffff);
- OUT_CS_REG(RADEON_DP_SRC_BKGD_CLR, 0x00000000);
- /* XXX what should this be? */
- OUT_CS_REG(RADEON_DP_WRITE_MASK, 0x00000000);
- OUT_CS_REG(RADEON_DP_CNTL,
- RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM);
- OUT_CS_REG(RADEON_DST_PITCH_OFFSET, 0x0);
- /* XXX fix this shit -> OUT_RELOC(dst, 0, RADEON_GEM_DOMAIN_VRAM) */
-
- /* Do the actual paint. */
- OUT_CS_REG(RADEON_DST_Y_X, (y << 16) | x);
- OUT_CS_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
-
- /* Let the 2D engine settle. */
- OUT_CS_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
- OUT_CS_REG(RADEON_WAIT_UNTIL,
- RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
- return 1;
+ 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,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height,
+ unsigned value)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ r300_blitter_save_states(r300);
+ util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
+
+ util_blitter_fill(r300->blitter,
+ dst, dstx, dsty, width, height, value);
}