summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/r300
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r--src/gallium/drivers/r300/Makefile5
-rw-r--r--src/gallium/drivers/r300/SConscript3
-rw-r--r--src/gallium/drivers/r300/r300_blit.c37
-rw-r--r--src/gallium/drivers/r300/r300_chipset.c10
-rw-r--r--src/gallium/drivers/r300/r300_chipset.h2
-rw-r--r--src/gallium/drivers/r300/r300_context.c109
-rw-r--r--src/gallium/drivers/r300/r300_context.h170
-rw-r--r--src/gallium/drivers/r300/r300_cs.h25
-rw-r--r--src/gallium/drivers/r300/r300_debug.c27
-rw-r--r--src/gallium/drivers/r300/r300_defines.h46
-rw-r--r--src/gallium/drivers/r300/r300_emit.c643
-rw-r--r--src/gallium/drivers/r300/r300_emit.h29
-rw-r--r--src/gallium/drivers/r300/r300_flush.c8
-rw-r--r--src/gallium/drivers/r300/r300_fs.c200
-rw-r--r--src/gallium/drivers/r300/r300_fs.h22
-rw-r--r--src/gallium/drivers/r300/r300_query.c72
-rw-r--r--src/gallium/drivers/r300/r300_reg.h74
-rw-r--r--src/gallium/drivers/r300/r300_render.c472
-rw-r--r--src/gallium/drivers/r300/r300_render.h42
-rw-r--r--src/gallium/drivers/r300/r300_resource.c83
-rw-r--r--src/gallium/drivers/r300/r300_screen.c185
-rw-r--r--src/gallium/drivers/r300/r300_screen.h29
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.c324
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.h134
-rw-r--r--src/gallium/drivers/r300/r300_state.c649
-rw-r--r--src/gallium/drivers/r300/r300_state.h30
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c241
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.h4
-rw-r--r--src/gallium/drivers/r300/r300_state_inlines.h92
-rw-r--r--src/gallium/drivers/r300/r300_state_invariant.c19
-rw-r--r--src/gallium/drivers/r300/r300_texture.c635
-rw-r--r--src/gallium/drivers/r300/r300_texture.h41
-rw-r--r--src/gallium/drivers/r300/r300_tgsi_to_rc.c24
-rw-r--r--src/gallium/drivers/r300/r300_transfer.c260
-rw-r--r--src/gallium/drivers/r300/r300_transfer.h51
-rw-r--r--src/gallium/drivers/r300/r300_vs.c226
-rw-r--r--src/gallium/drivers/r300/r300_vs.h21
-rw-r--r--src/gallium/drivers/r300/r300_winsys.h154
38 files changed, 3638 insertions, 1560 deletions
diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile
index 1f69daec81..5a8e00f15a 100644
--- a/src/gallium/drivers/r300/Makefile
+++ b/src/gallium/drivers/r300/Makefile
@@ -13,13 +13,16 @@ C_SOURCES = \
r300_fs.c \
r300_query.c \
r300_render.c \
+ r300_resource.c \
r300_screen.c \
+ r300_screen_buffer.c \
r300_state.c \
r300_state_derived.c \
r300_state_invariant.c \
r300_vs.c \
r300_texture.c \
- r300_tgsi_to_rc.c
+ r300_tgsi_to_rc.c \
+ r300_transfer.c
LIBRARY_INCLUDES = \
-I$(TOP)/src/mesa/drivers/dri/r300/compiler \
diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript
index 183aa17f9b..08aec427a1 100644
--- a/src/gallium/drivers/r300/SConscript
+++ b/src/gallium/drivers/r300/SConscript
@@ -23,13 +23,16 @@ r300 = env.ConvenienceLibrary(
'r300_fs.c',
'r300_query.c',
'r300_render.c',
+ 'r300_resource.c',
'r300_screen.c',
+ 'r300_screen_buffer.c',
'r300_state.c',
'r300_state_derived.c',
'r300_state_invariant.c',
'r300_vs.c',
'r300_texture.c',
'r300_tgsi_to_rc.c',
+ 'r300_transfer.c',
] + r300compiler) + r300compiler
Export('r300')
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 513cc0f5d4..e15c71eef6 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -32,10 +32,14 @@ static void r300_blitter_save_states(struct r300_context* r300)
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);
+ 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);
+ /* XXX this crashes the driver
+ util_blitter_save_vertex_buffers(r300->blitter, r300->vertex_buffer_count,
+ r300->vertex_buffer); */
}
/* Clear currently bound buffers. */
@@ -55,21 +59,10 @@ void r300_clear(struct pipe_context* pipe,
* 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
+ * 3) 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
+ * 4) 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
@@ -110,11 +103,12 @@ static void r300_hw_copy(struct pipe_context* pipe,
util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
util_blitter_save_fragment_sampler_states(
- r300->blitter, state->sampler_count, (void**)state->sampler_states);
+ r300->blitter, state->sampler_state_count,
+ (void**)state->sampler_states);
- util_blitter_save_fragment_sampler_textures(
- r300->blitter, state->texture_count,
- (struct pipe_texture**)state->textures);
+ 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,
@@ -136,8 +130,8 @@ void r300_surface_copy(struct pipe_context* pipe,
if (!pipe->screen->is_format_supported(pipe->screen,
old_format, src->texture->target,
- PIPE_TEXTURE_USAGE_RENDER_TARGET |
- PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_SAMPLER_VIEW, 0)) {
switch (util_format_get_blocksize(old_format)) {
case 1:
new_format = PIPE_FORMAT_I8_UNORM;
@@ -148,6 +142,9 @@ void r300_surface_copy(struct pipe_context* pipe,
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",
diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c
index 92de297ef1..c77e944b6d 100644
--- a/src/gallium/drivers/r300/r300_chipset.c
+++ b/src/gallium/drivers/r300/r300_chipset.c
@@ -24,6 +24,8 @@
#include "util/u_debug.h"
+#include <stdio.h>
+
/* r300_chipset: A file all to itself for deducing the various properties of
* Radeons. */
@@ -32,12 +34,12 @@ void r300_parse_chipset(struct r300_capabilities* caps)
{
/* Reasonable defaults */
caps->num_vert_fpus = 4;
+ caps->num_tex_units = 16;
caps->has_tcl = debug_get_bool_option("RADEON_NO_TCL", FALSE) ? FALSE : TRUE;
caps->is_r400 = FALSE;
caps->is_r500 = FALSE;
caps->high_second_pipe = FALSE;
-
/* Note: These are not ordered by PCI ID. I leave that task to GCC,
* which will perform the ordering while collating jump tables. Instead,
* I've tried to group them according to capabilities and age. */
@@ -106,6 +108,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x3150:
case 0x3152:
case 0x3154:
+ case 0x3155:
case 0x3E50:
case 0x3E54:
caps->family = CHIP_FAMILY_RV380;
@@ -365,8 +368,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
break;
default:
- debug_printf("r300: Warning: Unknown chipset 0x%x\n",
- caps->pci_id);
- break;
+ fprintf(stderr, "r300: Warning: Unknown chipset 0x%x\n",
+ caps->pci_id);
}
}
diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h
index 2808486492..ff957b7c29 100644
--- a/src/gallium/drivers/r300/r300_chipset.h
+++ b/src/gallium/drivers/r300/r300_chipset.h
@@ -38,6 +38,8 @@ struct r300_capabilities {
unsigned num_frag_pipes;
/* The number of z pipes */
unsigned num_z_pipes;
+ /* The number of texture units. */
+ unsigned num_tex_units;
/* Whether or not TCL is physically present */
boolean has_tcl;
/* Whether or not this is R400. The differences compared to their R3xx
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index 0d5ebdf589..deaa03e1f6 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -24,6 +24,7 @@
#include "util/u_memory.h"
#include "util/u_simple_list.h"
+#include "util/u_upload_mgr.h"
#include "r300_blit.h"
#include "r300_context.h"
@@ -32,10 +33,9 @@
#include "r300_query.h"
#include "r300_render.h"
#include "r300_screen.h"
+#include "r300_screen_buffer.h"
#include "r300_state_invariant.h"
-#include "r300_texture.h"
-
-#include "radeon_winsys.h"
+#include "r300_winsys.h"
static void r300_destroy_context(struct pipe_context* context)
{
@@ -46,7 +46,7 @@ static void r300_destroy_context(struct pipe_context* context)
draw_destroy(r300->draw);
/* Free the OQ BO. */
- context->screen->buffer_destroy(r300->oqbo);
+ context->screen->resource_destroy(context->screen, r300->oqbo);
/* If there are any queries pending or not destroyed, remove them now. */
foreach_s(query, temp, &r300->query_list) {
@@ -54,42 +54,23 @@ static void r300_destroy_context(struct pipe_context* context)
FREE(query);
}
+ u_upload_destroy(r300->upload_vb);
+ u_upload_destroy(r300->upload_ib);
+
FREE(r300->blend_color_state.state);
FREE(r300->clip_state.state);
FREE(r300->fb_state.state);
FREE(r300->rs_block_state.state);
FREE(r300->scissor_state.state);
FREE(r300->textures_state.state);
- FREE(r300->vertex_stream_state.state);
FREE(r300->vap_output_state.state);
FREE(r300->viewport_state.state);
FREE(r300->ztop_state.state);
+ FREE(r300->fs_constants.state);
+ FREE(r300->vs_constants.state);
FREE(r300);
}
-static unsigned int
-r300_is_texture_referenced(struct pipe_context *pipe,
- struct pipe_texture *texture,
- unsigned face, unsigned level)
-{
- struct pipe_buffer* buf = 0;
-
- r300_get_texture_buffer(pipe->screen, texture, &buf, NULL);
-
- return pipe->is_buffer_referenced(pipe, buf);
-}
-
-static unsigned int
-r300_is_buffer_referenced(struct pipe_context *pipe,
- struct pipe_buffer *buf)
-{
- /* This only checks to see whether actual hardware buffers are
- * referenced. Since we use managed BOs and transfers, it's actually not
- * possible for pipe_buffers to ever reference the actual hardware, so
- * buffers are never referenced. */
- return 0;
-}
-
static void r300_flush_cb(void *data)
{
struct r300_context* const cs_context_copy = data;
@@ -107,8 +88,8 @@ static void r300_flush_cb(void *data)
static void r300_setup_atoms(struct r300_context* r300)
{
- boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500;
- boolean has_tcl = r300_screen(r300->context.screen)->caps->has_tcl;
+ boolean is_r500 = r300->screen->caps.is_r500;
+ boolean has_tcl = r300->screen->caps.has_tcl;
/* Create the actual atom list.
*
@@ -119,6 +100,7 @@ static void r300_setup_atoms(struct r300_context* r300)
* the size of 0 here. */
make_empty_list(&r300->atom_list);
R300_INIT_ATOM(invariant_state, 71);
+ R300_INIT_ATOM(query_start, 4);
R300_INIT_ATOM(ztop_state, 2);
R300_INIT_ATOM(blend_state, 8);
R300_INIT_ATOM(blend_color_state, is_r500 ? 3 : 2);
@@ -133,8 +115,19 @@ static void r300_setup_atoms(struct r300_context* r300)
R300_INIT_ATOM(vap_output_state, 6);
R300_INIT_ATOM(pvs_flush, 2);
R300_INIT_ATOM(vs_state, 0);
+ R300_INIT_ATOM(vs_constants, 0);
R300_INIT_ATOM(texture_cache_inval, 2);
R300_INIT_ATOM(textures_state, 0);
+ R300_INIT_ATOM(fs, 0);
+ R300_INIT_ATOM(fs_rc_constant_state, 0);
+ R300_INIT_ATOM(fs_constants, 0);
+
+ /* Replace emission functions for r500. */
+ if (r300->screen->caps.is_r500) {
+ r300->fs.emit = r500_emit_fs;
+ r300->fs_rc_constant_state.emit = r500_emit_fs_rc_constant_state;
+ r300->fs_constants.emit = r500_emit_fs_constants;
+ }
/* Some non-CSO atoms need explicit space to store the state locally. */
r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state);
@@ -143,10 +136,11 @@ static void r300_setup_atoms(struct r300_context* r300)
r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block);
r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state);
r300->textures_state.state = CALLOC_STRUCT(r300_textures_state);
- r300->vertex_stream_state.state = CALLOC_STRUCT(r300_vertex_stream_state);
r300->vap_output_state.state = CALLOC_STRUCT(r300_vap_output_state);
r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state);
r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state);
+ r300->fs_constants.state = CALLOC_STRUCT(r300_constant_buffer);
+ r300->vs_constants.state = CALLOC_STRUCT(r300_constant_buffer);
}
struct pipe_context* r300_create_context(struct pipe_screen* screen,
@@ -154,14 +148,15 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
{
struct r300_context* r300 = CALLOC_STRUCT(r300_context);
struct r300_screen* r300screen = r300_screen(screen);
- struct radeon_winsys* radeon_winsys = r300screen->radeon_winsys;
+ struct r300_winsys_screen *rws = r300screen->rws;
if (!r300)
return NULL;
- r300->winsys = radeon_winsys;
+ r300->rws = rws;
+ r300->screen = r300screen;
- r300->context.winsys = (struct pipe_winsys*)radeon_winsys;
+ r300->context.winsys = (struct pipe_winsys*)rws;
r300->context.screen = screen;
r300->context.priv = priv;
@@ -171,10 +166,20 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300->context.surface_copy = r300_surface_copy;
r300->context.surface_fill = r300_surface_fill;
- if (r300screen->caps->has_tcl) {
+ if (r300screen->caps.has_tcl) {
r300->context.draw_arrays = r300_draw_arrays;
r300->context.draw_elements = r300_draw_elements;
r300->context.draw_range_elements = r300_draw_range_elements;
+
+ if (r300screen->caps.is_r500) {
+ r300->emit_draw_arrays_immediate = r500_emit_draw_arrays_immediate;
+ r300->emit_draw_arrays = r500_emit_draw_arrays;
+ r300->emit_draw_elements = r500_emit_draw_elements;
+ } else {
+ r300->emit_draw_arrays_immediate = r300_emit_draw_arrays_immediate;
+ r300->emit_draw_arrays = r300_emit_draw_arrays;
+ r300->emit_draw_elements = r300_emit_draw_elements;
+ }
} else {
r300->context.draw_arrays = r300_swtcl_draw_arrays;
r300->context.draw_elements = r300_draw_elements;
@@ -191,31 +196,43 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
draw_set_viewport_state(r300->draw, &r300_viewport_identity);
}
- r300->context.is_texture_referenced = r300_is_texture_referenced;
- r300->context.is_buffer_referenced = r300_is_buffer_referenced;
-
r300_setup_atoms(r300);
/* Open up the OQ BO. */
- r300->oqbo = screen->buffer_create(screen, 4096,
- PIPE_BUFFER_USAGE_VERTEX, 4096);
+ r300->oqbo = pipe_buffer_create(screen,
+ R300_BIND_OQBO, 4096);
make_empty_list(&r300->query_list);
r300_init_flush_functions(r300);
-
r300_init_query_functions(r300);
-
- /* r300_init_surface_functions(r300); */
-
r300_init_state_functions(r300);
+ r300_init_resource_functions(r300);
r300->invariant_state.dirty = TRUE;
- r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300);
- r300->dirty_state = R300_NEW_KITCHEN_SINK;
+ rws->set_flush_cb(r300->rws, r300_flush_cb, r300);
r300->dirty_hw++;
r300->blitter = util_blitter_create(&r300->context);
+ r300->upload_ib = u_upload_create(&r300->context,
+ 32 * 1024, 16,
+ PIPE_BIND_INDEX_BUFFER);
+
+ if (r300->upload_ib == NULL)
+ goto no_upload_ib;
+
+ r300->upload_vb = u_upload_create(&r300->context,
+ 128 * 1024, 16,
+ PIPE_BIND_VERTEX_BUFFER);
+ if (r300->upload_vb == NULL)
+ goto no_upload_vb;
+
return &r300->context;
+
+ no_upload_ib:
+ u_upload_destroy(r300->upload_ib);
+ no_upload_vb:
+ FREE(r300);
+ return NULL;
}
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 0d1518a05b..2e8601b65e 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -29,9 +29,12 @@
#include "pipe/p_context.h"
#include "util/u_inlines.h"
+#include "util/u_transfer.h"
+#include "r300_defines.h"
#include "r300_screen.h"
+struct u_upload_mgr;
struct r300_context;
struct r300_fragment_shader;
@@ -50,8 +53,6 @@ struct r300_atom {
unsigned size;
/* Whether this atom should be emitted. */
boolean dirty;
- /* Another dirty flag that is never automatically cleared. */
- boolean always_dirty;
};
struct r300_blend_state {
@@ -77,6 +78,11 @@ struct r300_dsa_state {
uint32_t z_stencil_control; /* R300_ZB_ZSTENCILCNTL: 0x4f04 */
uint32_t stencil_ref_mask; /* R300_ZB_STENCILREFMASK: 0x4f08 */
uint32_t stencil_ref_bf; /* R500_ZB_STENCILREFMASK_BF: 0x4fd4 */
+
+ /* Whether a two-sided stencil is enabled. */
+ boolean two_sided;
+ /* Whether a fallback should be used for a two-sided stencil ref value. */
+ boolean stencil_ref_bf_fallback;
};
struct r300_rs_state {
@@ -97,6 +103,17 @@ struct r300_rs_state {
uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */
uint32_t color_control; /* R300_GA_COLOR_CONTROL: 0x4278 */
uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */
+ uint32_t clip_rule; /* R300_SC_CLIP_RULE: 0x43D0 */
+
+ /* Specifies top of Raster pipe specific enable controls,
+ * i.e. texture coordinates stuffing for points, lines, triangles */
+ uint32_t stuffing_enable; /* R300_GB_ENABLE: 0x4008 */
+
+ /* Point sprites texture coordinates, 0: lower left, 1: upper right */
+ float point_texcoord_left; /* R300_GA_POINT_S0: 0x4200 */
+ float point_texcoord_bottom; /* R300_GA_POINT_T0: 0x4204 */
+ float point_texcoord_right; /* R300_GA_POINT_S1: 0x4208 */
+ float point_texcoord_top; /* R300_GA_POINT_T1: 0x420c */
};
struct r300_rs_block {
@@ -122,35 +139,44 @@ struct r300_texture_format_state {
uint32_t format0; /* R300_TX_FORMAT0: 0x4480 */
uint32_t format1; /* R300_TX_FORMAT1: 0x44c0 */
uint32_t format2; /* R300_TX_FORMAT2: 0x4500 */
+ uint32_t tile_config; /* R300_TX_OFFSET (subset thereof) */
+};
+
+struct r300_sampler_view {
+ struct pipe_sampler_view base;
+
+ /* Copy of r300_texture::texture_format_state with format-specific bits
+ * added. */
+ struct r300_texture_format_state format;
};
struct r300_texture_fb_state {
/* Colorbuffer. */
- uint32_t colorpitch[PIPE_MAX_TEXTURE_LEVELS]; /* R300_RB3D_COLORPITCH[0-3]*/
+ uint32_t colorpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_COLORPITCH[0-3]*/
uint32_t us_out_fmt; /* R300_US_OUT_FMT[0-3] */
/* Zbuffer. */
- uint32_t depthpitch[PIPE_MAX_TEXTURE_LEVELS]; /* R300_RB3D_DEPTHPITCH */
+ uint32_t depthpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_DEPTHPITCH */
uint32_t zb_format; /* R300_ZB_FORMAT */
};
struct r300_textures_state {
/* Textures. */
- struct r300_texture *textures[8];
- int texture_count;
+ struct r300_sampler_view *sampler_views[16];
+ int sampler_view_count;
/* Sampler states. */
- struct r300_sampler_state *sampler_states[8];
- int sampler_count;
+ struct r300_sampler_state *sampler_states[16];
+ int sampler_state_count;
- /* These is the merge of the texture and sampler states. */
+ /* This is the merge of the texture and sampler states. */
unsigned count;
uint32_t tx_enable; /* R300_TX_ENABLE: 0x4101 */
struct r300_texture_sampler_state {
- uint32_t format[3]; /* R300_TX_FORMAT[0-2] */
- uint32_t filter[2]; /* R300_TX_FILTER[0-1] */
+ struct r300_texture_format_state format;
+ uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */
+ uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */
uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */
- uint32_t tile_config; /* R300_TX_OFFSET (subset thereof) */
- } regs[8];
+ } regs[16];
};
struct r300_vertex_stream_state {
@@ -182,12 +208,6 @@ struct r300_ztop_state {
uint32_t z_buffer_top; /* R300_ZB_ZTOP: 0x4f14 */
};
-#define R300_NEW_FRAGMENT_SHADER 0x00000020
-#define R300_NEW_FRAGMENT_SHADER_CONSTANTS 0x00000040
-#define R300_NEW_VERTEX_SHADER_CONSTANTS 0x10000000
-#define R300_NEW_QUERY 0x40000000
-#define R300_NEW_KITCHEN_SINK 0x7fffffff
-
/* The next several objects are not pure Radeon state; they inherit from
* various Gallium classes. */
@@ -225,27 +245,21 @@ struct r300_query {
struct r300_query* next;
};
-enum r300_buffer_tiling {
- R300_BUFFER_LINEAR = 0,
- R300_BUFFER_TILED,
- R300_BUFFER_SQUARETILED
-};
-
struct r300_texture {
/* Parent class */
- struct pipe_texture tex;
+ struct u_resource b;
/* Offsets into the buffer. */
- unsigned offset[PIPE_MAX_TEXTURE_LEVELS];
+ unsigned offset[R300_MAX_TEXTURE_LEVELS];
/* A pitch for each mip-level */
- unsigned pitch[PIPE_MAX_TEXTURE_LEVELS];
+ unsigned pitch[R300_MAX_TEXTURE_LEVELS];
/* Size of one zslice or face based on the texture target */
- unsigned layer_size[PIPE_MAX_TEXTURE_LEVELS];
+ unsigned layer_size[R300_MAX_TEXTURE_LEVELS];
/* Whether the mipmap level is macrotiled. */
- enum r300_buffer_tiling mip_macrotile[PIPE_MAX_TEXTURE_LEVELS];
+ enum r300_buffer_tiling mip_macrotile[R300_MAX_TEXTURE_LEVELS];
/**
* If non-zero, override the natural texture layout with
@@ -260,42 +274,79 @@ struct r300_texture {
/* Total size of this texture, in bytes. */
unsigned size;
- /* Whether this texture has non-power-of-two dimensions.
+ /* Whether this texture has non-power-of-two dimensions
+ * or a user-specified pitch.
* It can be either a regular texture or a rectangle one.
*/
- boolean is_npot;
+ boolean uses_pitch;
/* Pipe buffer backing this texture. */
- struct pipe_buffer* buffer;
+ struct r300_winsys_buffer *buffer;
/* Registers carrying texture format data. */
- struct r300_texture_format_state state;
+ /* Only format-independent bits should be filled in. */
+ struct r300_texture_format_state tx_format;
+ /* All bits should be filled in. */
struct r300_texture_fb_state fb_state;
/* Buffer tiling */
enum r300_buffer_tiling microtile, macrotile;
};
+struct r300_vertex_info {
+ /* Parent class */
+ struct vertex_info vinfo;
+
+ /* R300_VAP_PROG_STREAK_CNTL_[0-7] */
+ uint32_t vap_prog_stream_cntl[8];
+ /* R300_VAP_PROG_STREAK_CNTL_EXT_[0-7] */
+ uint32_t vap_prog_stream_cntl_ext[8];
+};
+
+struct r300_vertex_element_state {
+ unsigned count;
+ struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
+
+ struct r300_vertex_stream_state vertex_stream;
+};
+
extern struct pipe_viewport_state r300_viewport_identity;
struct r300_context {
/* Parent class */
struct pipe_context context;
+ /* Emission of drawing packets. */
+ void (*emit_draw_arrays_immediate)(
+ struct r300_context *r300,
+ unsigned mode, unsigned start, unsigned count);
+
+ void (*emit_draw_arrays)(
+ struct r300_context *r300,
+ unsigned mode, unsigned count);
+
+ void (*emit_draw_elements)(
+ struct r300_context *r300, struct pipe_resource* indexBuffer,
+ unsigned indexSize, unsigned minIndex, unsigned maxIndex,
+ unsigned mode, unsigned start, unsigned count);
+
+
/* The interface to the windowing system, etc. */
- struct radeon_winsys* winsys;
+ struct r300_winsys_screen *rws;
+ /* Screen. */
+ struct r300_screen *screen;
/* Draw module. Used mostly for SW TCL. */
struct draw_context* draw;
/* Accelerated blit support. */
struct blitter_context* blitter;
/* Vertex buffer for rendering. */
- struct pipe_buffer* vbo;
+ struct pipe_resource* vbo;
/* Offset into the VBO. */
size_t vbo_offset;
/* Occlusion query buffer. */
- struct pipe_buffer* oqbo;
+ struct pipe_resource* oqbo;
/* Query list. */
struct r300_query *query_current;
struct r300_query query_list;
@@ -309,14 +360,18 @@ struct r300_context {
struct r300_atom blend_color_state;
/* User clip planes. */
struct r300_atom clip_state;
- /* Shader constants. */
- struct r300_constant_buffer shader_constants[PIPE_SHADER_TYPES];
/* Depth, stencil, and alpha state. */
struct r300_atom dsa_state;
/* Fragment shader. */
- struct r300_fragment_shader* fs;
+ struct r300_atom fs;
+ /* Fragment shader RC_CONSTANT_STATE variables. */
+ struct r300_atom fs_rc_constant_state;
+ /* Fragment shader constant buffer. */
+ struct r300_atom fs_constants;
/* Framebuffer state. */
struct r300_atom fb_state;
+ /* Occlusion query. */
+ struct r300_atom query_start;
/* Rasterizer state. */
struct r300_atom rs_state;
/* RS block state. */
@@ -331,6 +386,8 @@ struct r300_context {
struct r300_atom vap_output_state;
/* Vertex shader. */
struct r300_atom vs_state;
+ /* Vertex shader constant buffer. */
+ struct r300_atom vs_constants;
/* Viewport state. */
struct r300_atom viewport_state;
/* ZTOP state. */
@@ -348,8 +405,8 @@ struct r300_context {
int vertex_buffer_count;
int vertex_buffer_max_index;
/* Vertex elements for Gallium. */
- struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
- int vertex_element_count;
+ struct r300_vertex_element_state *velems;
+ bool any_user_vbs;
/* Vertex info for Draw. */
struct vertex_info vertex_info;
@@ -360,22 +417,40 @@ struct r300_context {
struct pipe_viewport_state viewport;
- /* Bitmask of dirty state objects. */
- uint32_t dirty_state;
/* Flag indicating whether or not the HW is dirty. */
uint32_t dirty_hw;
/* Whether polygon offset is enabled. */
boolean polygon_offset_enabled;
/* Z buffer bit depth. */
uint32_t zbuffer_bpp;
+ /* Whether rendering is conditional and should be skipped. */
+ boolean skip_rendering;
+ /* Whether the two-sided stencil ref value is different for front and
+ * back faces, and fallback should be used for r3xx-r4xx. */
+ boolean stencil_ref_bf_fallback;
+ /* Point sprites texcoord index, 1 bit per texcoord */
+ int sprite_coord_enable;
+
+ /* upload managers */
+ struct u_upload_mgr *upload_vb;
+ struct u_upload_mgr *upload_ib;
};
/* Convenience cast wrapper. */
+static INLINE struct r300_texture* r300_texture(struct pipe_resource* tex)
+{
+ return (struct r300_texture*)tex;
+}
+
static INLINE struct r300_context* r300_context(struct pipe_context* context)
{
return (struct r300_context*)context;
}
+static INLINE struct r300_fragment_shader *r300_fs(struct r300_context *r300)
+{
+ return (struct r300_fragment_shader*)r300->fs.state;
+}
struct pipe_context* r300_create_context(struct pipe_screen* screen,
void *priv);
@@ -383,11 +458,11 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
/* Context initialization. */
struct draw_stage* r300_draw_stage(struct r300_context* r300);
void r300_init_state_functions(struct r300_context* r300);
-void r300_init_surface_functions(struct r300_context* r300);
+void r300_init_resource_functions(struct r300_context* r300);
static INLINE boolean CTX_DBG_ON(struct r300_context * ctx, unsigned flags)
{
- return SCREEN_DBG_ON(r300_screen(ctx->context.screen), flags);
+ return SCREEN_DBG_ON(ctx->screen, flags);
}
static INLINE void CTX_DBG(struct r300_context * ctx, unsigned flags,
@@ -396,7 +471,7 @@ static INLINE void CTX_DBG(struct r300_context * ctx, unsigned flags,
if (CTX_DBG_ON(ctx, flags)) {
va_list va;
va_start(va, fmt);
- debug_vprintf(fmt, va);
+ vfprintf(stderr, fmt, va);
va_end(va);
}
}
@@ -405,4 +480,3 @@ static INLINE void CTX_DBG(struct r300_context * ctx, unsigned flags,
#define DBG CTX_DBG
#endif /* R300_CONTEXT_H */
-
diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h
index 151f72b0fe..456b2ec7b9 100644
--- a/src/gallium/drivers/r300/r300_cs.h
+++ b/src/gallium/drivers/r300/r300_cs.h
@@ -26,8 +26,7 @@
#include "util/u_math.h"
#include "r300_reg.h"
-
-#include "radeon_winsys.h"
+#include "r300_winsys.h"
/* Yes, I know macros are ugly. However, they are much prettier than the code
* that they neatly hide away, and don't have the cost of function setup,so
@@ -51,7 +50,7 @@
#define CS_LOCALS(context) \
struct r300_context* const cs_context_copy = (context); \
- struct radeon_winsys* cs_winsys = cs_context_copy->winsys; \
+ struct r300_winsys_screen *cs_winsys = cs_context_copy->rws; \
int cs_count = 0; (void) cs_count;
#define CHECK_CS(size) \
@@ -105,22 +104,34 @@
cs_count--; \
} while (0)
-#define OUT_CS_RELOC(bo, offset, rd, wd, flags) do { \
+#define OUT_CS_BUF_RELOC(bo, offset, rd, wd, flags) do { \
DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, offset %d, " \
"domains (%d, %d, %d)\n", \
bo, offset, rd, wd, flags); \
assert(bo); \
cs_winsys->write_cs_dword(cs_winsys, offset); \
- cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \
+ r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \
+ cs_count -= 3; \
+} while (0)
+
+
+#define OUT_CS_TEX_RELOC(tex, offset, rd, wd, flags) do { \
+ DBG(cs_context_copy, DBG_CS, "r300: writing relocation for texture %p, offset %d, " \
+ "domains (%d, %d, %d)\n", \
+ tex, offset, rd, wd, flags); \
+ assert(tex); \
+ cs_winsys->write_cs_dword(cs_winsys, offset); \
+ r300_texture_write_reloc(cs_winsys, tex, rd, wd, flags); \
cs_count -= 3; \
} while (0)
-#define OUT_CS_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \
+
+#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \
DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, " \
"domains (%d, %d, %d)\n", \
bo, rd, wd, flags); \
assert(bo); \
- cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \
+ r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \
cs_count -= 2; \
} while (0)
diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c
index b881730848..6e84bf8246 100644
--- a/src/gallium/drivers/r300/r300_debug.c
+++ b/src/gallium/drivers/r300/r300_debug.c
@@ -22,6 +22,7 @@
#include "r300_context.h"
+#include <stdio.h>
struct debug_option {
const char * name;
@@ -31,12 +32,15 @@ struct debug_option {
static struct debug_option debug_options[] = {
{ "help", DBG_HELP, "Helpful meta-information about the driver" },
- { "fp", DBG_FP, "Fragment program handling" },
- { "vp", DBG_VP, "Vertex program handling" },
- { "cs", DBG_CS, "Command submissions" },
- { "draw", DBG_DRAW, "Draw and emit" },
- { "tex", DBG_TEX, "Textures" },
- { "fall", DBG_FALL, "Fallbacks" },
+ { "fp", DBG_FP, "Fragment program handling (for debugging)" },
+ { "vp", DBG_VP, "Vertex program handling (for debugging)" },
+ { "cs", DBG_CS, "Command submissions (for debugging)" },
+ { "draw", DBG_DRAW, "Draw and emit (for debugging)" },
+ { "tex", DBG_TEX, "Textures (for debugging)" },
+ { "fall", DBG_FALL, "Fallbacks (for debugging)" },
+ { "anisohq", DBG_ANISOHQ, "High quality anisotropic filtering (for benchmarking)" },
+ { "notiling", DBG_NO_TILING, "Disable tiling (for benchmarking)" },
+ { "noimmd", DBG_NO_IMMD, "Disable immediate mode (for benchmarking)" },
{ "all", ~0, "Convenience option that enables all debug flags" },
@@ -68,7 +72,7 @@ void r300_init_debug(struct r300_screen * screen)
}
if (!opt->name) {
- debug_printf("Unknown debug option: %s\n", options);
+ fprintf(stderr, "Unknown debug option: %s\n", options);
printhint = TRUE;
}
@@ -80,10 +84,13 @@ void r300_init_debug(struct r300_screen * screen)
}
if (printhint || screen->debug & DBG_HELP) {
- debug_printf("You can enable debug output by setting the RADEON_DEBUG environment variable\n"
- "to a comma-separated list of debug options. Available options are:\n");
+ fprintf(stderr, "You can enable debug output by setting "
+ "the RADEON_DEBUG environment variable\n"
+ "to a comma-separated list of debug options. "
+ "Available options are:\n");
+
for(opt = debug_options; opt->name; ++opt) {
- debug_printf(" %s: %s\n", opt->name, opt->description);
+ fprintf(stderr, " %s: %s\n", opt->name, opt->description);
}
}
}
diff --git a/src/gallium/drivers/r300/r300_defines.h b/src/gallium/drivers/r300/r300_defines.h
new file mode 100644
index 0000000000..98ee3c1ede
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_defines.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010 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"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_DEFINES_H
+#define R300_DEFINES_H
+
+#include "pipe/p_defines.h"
+
+#define R300_MAX_TEXTURE_LEVELS 13
+#define R300_MAX_DRAW_VBO_SIZE (1024 * 1024)
+
+#define R300_RESOURCE_FLAG_TRANSFER PIPE_RESOURCE_FLAG_DRV_PRIV
+
+/* XXX: this is just a bandaid on larger problems in
+ * r300_screen_buffer.h which doesn't seem to be fully ported to
+ * gallium-resources.
+ */
+#define R300_BIND_OQBO (1<<21)
+
+/* Tiling flags. */
+enum r300_buffer_tiling {
+ R300_BUFFER_LINEAR = 0,
+ R300_BUFFER_TILED,
+ R300_BUFFER_SQUARETILED
+};
+
+#endif
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index addb28bded..19acdaba62 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -32,6 +32,7 @@
#include "r300_emit.h"
#include "r300_fs.h"
#include "r300_screen.h"
+#include "r300_screen_buffer.h"
#include "r300_vs.h"
void r300_emit_blend_state(struct r300_context* r300,
@@ -63,10 +64,9 @@ void r300_emit_blend_color_state(struct r300_context* r300,
unsigned size, void* state)
{
struct r300_blend_color_state* bc = (struct r300_blend_color_state*)state;
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
CS_LOCALS(r300);
- if (r300screen->caps->is_r500) {
+ if (r300->screen->caps.is_r500) {
BEGIN_CS(size);
OUT_CS_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2);
OUT_CS(bc->blend_color_red_alpha);
@@ -84,13 +84,12 @@ void r300_emit_clip_state(struct r300_context* r300,
{
struct pipe_clip_state* clip = (struct pipe_clip_state*)state;
int i;
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
CS_LOCALS(r300);
- if (r300screen->caps->has_tcl) {
+ if (r300->screen->caps.has_tcl) {
BEGIN_CS(size);
OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG,
- (r300screen->caps->is_r500 ?
+ (r300->screen->caps.is_r500 ?
R500_PVS_UCP_START : R300_PVS_UCP_START));
OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, 6 * 4);
for (i = 0; i < 6; i++) {
@@ -113,7 +112,6 @@ void r300_emit_clip_state(struct r300_context* r300,
void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state)
{
struct r300_dsa_state* dsa = (struct r300_dsa_state*)state;
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
struct pipe_framebuffer_state* fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
struct pipe_stencil_ref stencil_ref = r300->stencil_ref;
@@ -133,68 +131,47 @@ void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state)
OUT_CS(dsa->stencil_ref_mask | stencil_ref.ref_value[0]);
- if (r300screen->caps->is_r500) {
+ if (r300->screen->caps.is_r500) {
OUT_CS_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf | stencil_ref.ref_value[1]);
}
END_CS;
}
-static const float * get_shader_constant(
+static const float * get_rc_constant_state(
struct r300_context * r300,
- struct rc_constant * constant,
- struct r300_constant_buffer * externals)
+ struct rc_constant * constant)
{
- struct r300_viewport_state* viewport =
- (struct r300_viewport_state*)r300->viewport_state.state;
- struct r300_textures_state* texstate =
- (struct r300_textures_state*)r300->textures_state.state;
+ struct r300_viewport_state* viewport = r300->viewport_state.state;
+ struct r300_textures_state* texstate = r300->textures_state.state;
static float vec[4] = { 0.0, 0.0, 0.0, 1.0 };
- struct pipe_texture *tex;
-
- switch(constant->Type) {
- case RC_CONSTANT_EXTERNAL:
- return externals->constants[constant->u.External];
-
- case RC_CONSTANT_IMMEDIATE:
- return constant->u.Immediate;
-
- case RC_CONSTANT_STATE:
- switch (constant->u.State[0]) {
- /* Factor for converting rectangle coords to
- * normalized coords. Should only show up on non-r500. */
- case RC_STATE_R300_TEXRECT_FACTOR:
- tex = &texstate->textures[constant->u.State[1]]->tex;
- vec[0] = 1.0 / tex->width0;
- vec[1] = 1.0 / tex->height0;
- break;
-
- /* Texture compare-fail value. Shouldn't ever show up, but if
- * it does, we'll be ready. */
- case RC_STATE_SHADOW_AMBIENT:
- vec[3] = 0;
- break;
-
- case RC_STATE_R300_VIEWPORT_SCALE:
- vec[0] = viewport->xscale;
- vec[1] = viewport->yscale;
- vec[2] = viewport->zscale;
- break;
-
- case RC_STATE_R300_VIEWPORT_OFFSET:
- vec[0] = viewport->xoffset;
- vec[1] = viewport->yoffset;
- vec[2] = viewport->zoffset;
- break;
-
- default:
- debug_printf("r300: Implementation error: "
- "Unknown RC_CONSTANT type %d\n", constant->u.State[0]);
- }
+ struct pipe_resource *tex;
+
+ assert(constant->Type == RC_CONSTANT_STATE);
+
+ switch (constant->u.State[0]) {
+ /* Factor for converting rectangle coords to
+ * normalized coords. Should only show up on non-r500. */
+ case RC_STATE_R300_TEXRECT_FACTOR:
+ tex = texstate->sampler_views[constant->u.State[1]]->base.texture;
+ vec[0] = 1.0 / tex->width0;
+ vec[1] = 1.0 / tex->height0;
+ break;
+
+ case RC_STATE_R300_VIEWPORT_SCALE:
+ vec[0] = viewport->xscale;
+ vec[1] = viewport->yscale;
+ vec[2] = viewport->zscale;
+ break;
+
+ case RC_STATE_R300_VIEWPORT_OFFSET:
+ vec[0] = viewport->xoffset;
+ vec[1] = viewport->yoffset;
+ vec[2] = viewport->zoffset;
break;
default:
- debug_printf("r300: Implementation error: "
- "Unhandled constant type %d\n", constant->Type);
+ fprintf(stderr, "r300: Implementation error: "
+ "Unknown RC_CONSTANT type %d\n", constant->u.State[0]);
}
/* This should either be (0, 0, 0, 1), which should be a relatively safe
@@ -237,17 +214,31 @@ static uint32_t pack_float24(float f)
return float24;
}
-void r300_emit_fragment_program_code(struct r300_context* r300,
- struct rX00_fragment_program_code* generic_code)
+unsigned r300_get_fs_atom_size(struct r300_context *r300)
+{
+ struct r300_fragment_shader *fs = r300_fs(r300);
+ unsigned imm_count = fs->shader->immediates_count;
+ struct r300_fragment_program_code *code = &fs->shader->code.code.r300;
+
+ return 19 +
+ code->alu.length * 4 +
+ (code->tex.length ? (1 + code->tex.length) : 0) +
+ (imm_count ? imm_count * 5 : 0);
+}
+
+void r300_emit_fs(struct r300_context* r300, unsigned size, void *state)
{
+ struct r300_fragment_shader *fs = r300_fs(r300);
+ struct rX00_fragment_program_code* generic_code = &fs->shader->code;
struct r300_fragment_program_code * code = &generic_code->code.r300;
- int i;
+ unsigned i;
+ unsigned imm_count = fs->shader->immediates_count;
+ unsigned imm_first = fs->shader->externals_count;
+ unsigned imm_end = generic_code->constants.Count;
+ struct rc_constant *constants = generic_code->constants.Constants;
CS_LOCALS(r300);
- BEGIN_CS(15 +
- code->alu.length * 4 +
- (code->tex.length ? (1 + code->tex.length) : 0));
-
+ BEGIN_CS(size);
OUT_CS_REG(R300_US_CONFIG, code->config);
OUT_CS_REG(R300_US_PIXSIZE, code->pixsize);
OUT_CS_REG(R300_US_CODE_OFFSET, code->code_offset);
@@ -278,24 +269,43 @@ void r300_emit_fragment_program_code(struct r300_context* r300,
OUT_CS(code->tex.inst[i]);
}
+ /* Emit immediates. */
+ if (imm_count) {
+ for(i = imm_first; i < imm_end; ++i) {
+ if (constants[i].Type == RC_CONSTANT_IMMEDIATE) {
+ const float *data = constants[i].u.Immediate;
+
+ OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4);
+ OUT_CS(pack_float24(data[0]));
+ OUT_CS(pack_float24(data[1]));
+ OUT_CS(pack_float24(data[2]));
+ OUT_CS(pack_float24(data[3]));
+ }
+ }
+ }
+
+ OUT_CS_REG(R300_FG_DEPTH_SRC, fs->shader->fg_depth_src);
+ OUT_CS_REG(R300_US_W_FMT, fs->shader->us_out_w);
END_CS;
}
-void r300_emit_fs_constant_buffer(struct r300_context* r300,
- struct rc_constant_list* constants)
+void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state)
{
- int i;
+ struct r300_fragment_shader *fs = r300_fs(r300);
+ struct rc_constant_list *constants = &fs->shader->code.constants;
+ struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state;
+ unsigned i, count = fs->shader->externals_count;
CS_LOCALS(r300);
- if (constants->Count == 0)
+ if (count == 0)
return;
- BEGIN_CS(constants->Count * 4 + 1);
- OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, constants->Count * 4);
- for(i = 0; i < constants->Count; ++i) {
- const float * data = get_shader_constant(r300,
- &constants->Constants[i],
- &r300->shader_constants[PIPE_SHADER_FRAGMENT]);
+ BEGIN_CS(size);
+ OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count * 4);
+ for(i = 0; i < count; ++i) {
+ const float *data;
+ assert(constants->Constants[i].Type == RC_CONSTANT_EXTERNAL);
+ data = buf->constants[i];
OUT_CS(pack_float24(data[0]));
OUT_CS(pack_float24(data[1]));
OUT_CS(pack_float24(data[2]));
@@ -304,31 +314,59 @@ void r300_emit_fs_constant_buffer(struct r300_context* r300,
END_CS;
}
-static void r300_emit_fragment_depth_config(struct r300_context* r300,
- struct r300_fragment_shader* fs)
+void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state)
{
+ struct r300_fragment_shader *fs = r300_fs(r300);
+ struct rc_constant_list *constants = &fs->shader->code.constants;
+ unsigned i;
+ unsigned count = fs->shader->rc_state_count;
+ unsigned first = fs->shader->externals_count;
+ unsigned end = constants->Count;
CS_LOCALS(r300);
- BEGIN_CS(4);
- if (r300_fragment_shader_writes_depth(fs)) {
- OUT_CS_REG(R300_FG_DEPTH_SRC, R300_FG_DEPTH_SRC_SHADER);
- OUT_CS_REG(R300_US_W_FMT, R300_W_FMT_W24 | R300_W_SRC_US);
- } else {
- OUT_CS_REG(R300_FG_DEPTH_SRC, R300_FG_DEPTH_SRC_SCAN);
- OUT_CS_REG(R300_US_W_FMT, R300_W_FMT_W0 | R300_W_SRC_US);
+ if (count == 0)
+ return;
+
+ BEGIN_CS(size);
+ for(i = first; i < end; ++i) {
+ if (constants->Constants[i].Type == RC_CONSTANT_STATE) {
+ const float *data =
+ get_rc_constant_state(r300, &constants->Constants[i]);
+
+ OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4);
+ OUT_CS(pack_float24(data[0]));
+ OUT_CS(pack_float24(data[1]));
+ OUT_CS(pack_float24(data[2]));
+ OUT_CS(pack_float24(data[3]));
+ }
}
END_CS;
}
-void r500_emit_fragment_program_code(struct r300_context* r300,
- struct rX00_fragment_program_code* generic_code)
+unsigned r500_get_fs_atom_size(struct r300_context *r300)
+{
+ struct r300_fragment_shader *fs = r300_fs(r300);
+ unsigned imm_count = fs->shader->immediates_count;
+ struct r500_fragment_program_code *code = &fs->shader->code.code.r500;
+
+ return 17 +
+ ((code->inst_end + 1) * 6) +
+ (imm_count ? imm_count * 7 : 0);
+}
+
+void r500_emit_fs(struct r300_context* r300, unsigned size, void *state)
{
+ struct r300_fragment_shader *fs = r300_fs(r300);
+ struct rX00_fragment_program_code* generic_code = &fs->shader->code;
struct r500_fragment_program_code * code = &generic_code->code.r500;
- int i;
+ unsigned i;
+ unsigned imm_count = fs->shader->immediates_count;
+ unsigned imm_first = fs->shader->externals_count;
+ unsigned imm_end = generic_code->constants.Count;
+ struct rc_constant *constants = generic_code->constants.Constants;
CS_LOCALS(r300);
- BEGIN_CS(13 +
- ((code->inst_end + 1) * 6));
+ BEGIN_CS(size);
OUT_CS_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
OUT_CS_REG(R500_US_PIXSIZE, code->max_temp_idx);
OUT_CS_REG(R500_US_CODE_RANGE,
@@ -348,25 +386,48 @@ void r500_emit_fragment_program_code(struct r300_context* r300,
OUT_CS(code->inst[i].inst5);
}
+ /* Emit immediates. */
+ if (imm_count) {
+ for(i = imm_first; i < imm_end; ++i) {
+ if (constants[i].Type == RC_CONSTANT_IMMEDIATE) {
+ const float *data = constants[i].u.Immediate;
+
+ OUT_CS_REG(R500_GA_US_VECTOR_INDEX,
+ R500_GA_US_VECTOR_INDEX_TYPE_CONST |
+ (i & R500_GA_US_VECTOR_INDEX_MASK));
+ OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4);
+ OUT_CS_32F(data[0]);
+ OUT_CS_32F(data[1]);
+ OUT_CS_32F(data[2]);
+ OUT_CS_32F(data[3]);
+ }
+ }
+ }
+
+ OUT_CS_REG(R300_FG_DEPTH_SRC, fs->shader->fg_depth_src);
+ OUT_CS_REG(R300_US_W_FMT, fs->shader->us_out_w);
END_CS;
}
-void r500_emit_fs_constant_buffer(struct r300_context* r300,
- struct rc_constant_list* constants)
+void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state)
{
- int i;
+ struct r300_fragment_shader *fs = r300_fs(r300);
+ struct rc_constant_list *constants = &fs->shader->code.constants;
+ struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state;
+ unsigned i, count = fs->shader->externals_count;
CS_LOCALS(r300);
- if (constants->Count == 0)
+ if (count == 0)
return;
- BEGIN_CS(constants->Count * 4 + 3);
+ BEGIN_CS(size);
OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST);
- OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, constants->Count * 4);
- for (i = 0; i < constants->Count; i++) {
- const float * data = get_shader_constant(r300,
- &constants->Constants[i],
- &r300->shader_constants[PIPE_SHADER_FRAGMENT]);
+ OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count * 4);
+ for(i = 0; i < count; ++i) {
+ const float *data;
+ assert(constants->Constants[i].Type == RC_CONSTANT_EXTERNAL);
+ data = buf->constants[i];
+
OUT_CS_32F(data[0]);
OUT_CS_32F(data[1]);
OUT_CS_32F(data[2]);
@@ -375,10 +436,41 @@ void r500_emit_fs_constant_buffer(struct r300_context* r300,
END_CS;
}
+void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state)
+{
+ struct r300_fragment_shader *fs = r300_fs(r300);
+ struct rc_constant_list *constants = &fs->shader->code.constants;
+ unsigned i;
+ unsigned count = fs->shader->rc_state_count;
+ unsigned first = fs->shader->externals_count;
+ unsigned end = constants->Count;
+ CS_LOCALS(r300);
+
+ if (count == 0)
+ return;
+
+ BEGIN_CS(size);
+ for(i = first; i < end; ++i) {
+ if (constants->Constants[i].Type == RC_CONSTANT_STATE) {
+ const float *data =
+ get_rc_constant_state(r300, &constants->Constants[i]);
+
+ OUT_CS_REG(R500_GA_US_VECTOR_INDEX,
+ R500_GA_US_VECTOR_INDEX_TYPE_CONST |
+ (i & R500_GA_US_VECTOR_INDEX_MASK));
+ OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4);
+ OUT_CS_32F(data[0]);
+ OUT_CS_32F(data[1]);
+ OUT_CS_32F(data[2]);
+ OUT_CS_32F(data[3]);
+ }
+ }
+ END_CS;
+}
+
void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
{
struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state;
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
struct r300_texture* tex;
struct pipe_surface* surf;
int i;
@@ -396,7 +488,7 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
/* Set the number of colorbuffers. */
if (fb->nr_cbufs > 1) {
- if (r300screen->caps->is_r500) {
+ if (r300->screen->caps.is_r500) {
OUT_CS_REG(R300_RB3D_CCTL,
R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs) |
R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE);
@@ -411,14 +503,14 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
/* Set up colorbuffers. */
for (i = 0; i < fb->nr_cbufs; i++) {
surf = fb->cbufs[i];
- tex = (struct r300_texture*)surf->texture;
+ tex = r300_texture(surf->texture);
assert(tex && tex->buffer && "cbuf is marked, but NULL!");
OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1);
- OUT_CS_RELOC(tex->buffer, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_CS_TEX_RELOC(tex, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0);
OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1);
- OUT_CS_RELOC(tex->buffer, tex->fb_state.colorpitch[surf->level],
+ OUT_CS_TEX_RELOC(tex, tex->fb_state.colorpitch[surf->level],
0, RADEON_GEM_DOMAIN_VRAM, 0);
OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), tex->fb_state.us_out_fmt);
@@ -430,35 +522,45 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
/* Set up a zbuffer. */
if (fb->zsbuf) {
surf = fb->zsbuf;
- tex = (struct r300_texture*)surf->texture;
+ tex = r300_texture(surf->texture);
assert(tex && tex->buffer && "zsbuf is marked, but NULL!");
OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
- OUT_CS_RELOC(tex->buffer, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_CS_TEX_RELOC(tex, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0);
OUT_CS_REG(R300_ZB_FORMAT, tex->fb_state.zb_format);
OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
- OUT_CS_RELOC(tex->buffer, tex->fb_state.depthpitch[surf->level],
+ OUT_CS_TEX_RELOC(tex, tex->fb_state.depthpitch[surf->level],
0, RADEON_GEM_DOMAIN_VRAM, 0);
}
+ OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
+ if (r300->screen->caps.is_r500) {
+ OUT_CS(0);
+ OUT_CS(((fb->width - 1) << R300_SCISSORS_X_SHIFT) |
+ ((fb->height - 1) << R300_SCISSORS_Y_SHIFT));
+ } else {
+ OUT_CS((1440 << R300_SCISSORS_X_SHIFT) |
+ (1440 << R300_SCISSORS_Y_SHIFT));
+ OUT_CS(((fb->width + 1440-1) << R300_SCISSORS_X_SHIFT) |
+ ((fb->height + 1440-1) << R300_SCISSORS_Y_SHIFT));
+ }
OUT_CS_REG(R300_GA_POINT_MINMAX,
(MAX2(fb->width, fb->height) * 6) << R300_GA_POINT_MINMAX_MAX_SHIFT);
END_CS;
}
-static void r300_emit_query_start(struct r300_context *r300)
+void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state)
{
- struct r300_capabilities *caps = r300_screen(r300->context.screen)->caps;
struct r300_query *query = r300->query_current;
CS_LOCALS(r300);
if (!query)
return;
- BEGIN_CS(4);
- if (caps->family == CHIP_FAMILY_RV530) {
+ BEGIN_CS(size);
+ if (r300->screen->caps.family == CHIP_FAMILY_RV530) {
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
} else {
OUT_CS_REG(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL);
@@ -472,7 +574,7 @@ static void r300_emit_query_start(struct r300_context *r300)
static void r300_emit_query_finish(struct r300_context *r300,
struct r300_query *query)
{
- struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps;
+ struct r300_capabilities* caps = &r300->screen->caps;
CS_LOCALS(r300);
assert(caps->num_frag_pipes);
@@ -491,13 +593,13 @@ static void r300_emit_query_finish(struct r300_context *r300,
/* pipe 3 only */
OUT_CS_REG(R300_SU_REG_DEST, 1 << 3);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3),
+ OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3),
0, RADEON_GEM_DOMAIN_GTT, 0);
case 3:
/* pipe 2 only */
OUT_CS_REG(R300_SU_REG_DEST, 1 << 2);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2),
+ OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2),
0, RADEON_GEM_DOMAIN_GTT, 0);
case 2:
/* pipe 1 only */
@@ -505,19 +607,19 @@ static void r300_emit_query_finish(struct r300_context *r300,
OUT_CS_REG(R300_SU_REG_DEST,
1 << (caps->high_second_pipe ? 3 : 1));
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1),
+ OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1),
0, RADEON_GEM_DOMAIN_GTT, 0);
case 1:
/* pipe 0 only */
OUT_CS_REG(R300_SU_REG_DEST, 1 << 0);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0),
+ OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0),
0, RADEON_GEM_DOMAIN_GTT, 0);
break;
default:
- debug_printf("r300: Implementation error: Chipset reports %d"
+ fprintf(stderr, "r300: Implementation error: Chipset reports %d"
" pixel pipes!\n", caps->num_frag_pipes);
- assert(0);
+ abort();
}
/* And, finally, reset it to normal... */
@@ -533,7 +635,7 @@ static void rv530_emit_query_single(struct r300_context *r300,
BEGIN_CS(8);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+ OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
END_CS;
}
@@ -546,17 +648,17 @@ static void rv530_emit_query_double(struct r300_context *r300,
BEGIN_CS(14);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+ OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+ OUT_CS_BUF_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
END_CS;
}
void r300_emit_query_end(struct r300_context* r300)
{
- struct r300_capabilities *caps = r300_screen(r300->context.screen)->caps;
+ struct r300_capabilities *caps = &r300->screen->caps;
struct r300_query *query = r300->query_current;
if (!query)
@@ -614,6 +716,13 @@ void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state)
OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config);
OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value);
OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode);
+ OUT_CS_REG(R300_SC_CLIP_RULE, rs->clip_rule);
+ OUT_CS_REG(R300_GB_ENABLE, rs->stuffing_enable);
+ OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4);
+ OUT_CS_32F(rs->point_texcoord_left);
+ OUT_CS_32F(rs->point_texcoord_bottom);
+ OUT_CS_32F(rs->point_texcoord_right);
+ OUT_CS_32F(rs->point_texcoord_top);
END_CS;
}
@@ -622,7 +731,6 @@ void r300_emit_rs_block_state(struct r300_context* r300,
{
struct r300_rs_block* rs = (struct r300_rs_block*)state;
unsigned i;
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
/* It's the same for both INST and IP tables */
unsigned count = (rs->inst_count & R300_RS_INST_COUNT_MASK) + 1;
CS_LOCALS(r300);
@@ -630,7 +738,7 @@ void r300_emit_rs_block_state(struct r300_context* r300,
DBG(r300, DBG_DRAW, "r300: RS emit:\n");
BEGIN_CS(size);
- if (r300screen->caps->is_r500) {
+ if (r300->screen->caps.is_r500) {
OUT_CS_REG_SEQ(R500_RS_IP_0, count);
} else {
OUT_CS_REG_SEQ(R300_RS_IP_0, count);
@@ -644,7 +752,7 @@ void r300_emit_rs_block_state(struct r300_context* r300,
OUT_CS(rs->count);
OUT_CS(rs->inst_count);
- if (r300screen->caps->is_r500) {
+ if (r300->screen->caps.is_r500) {
OUT_CS_REG_SEQ(R500_RS_INST_0, count);
} else {
OUT_CS_REG_SEQ(R300_RS_INST_0, count);
@@ -663,62 +771,22 @@ void r300_emit_rs_block_state(struct r300_context* r300,
void r300_emit_scissor_state(struct r300_context* r300,
unsigned size, void* state)
{
- unsigned minx, miny, maxx, maxy;
- uint32_t top_left, bottom_right;
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state;
- struct pipe_framebuffer_state* fb =
- (struct pipe_framebuffer_state*)r300->fb_state.state;
CS_LOCALS(r300);
- minx = miny = 0;
- maxx = fb->width;
- maxy = fb->height;
-
- if (((struct r300_rs_state*)r300->rs_state.state)->rs.scissor) {
- minx = MAX2(minx, scissor->minx);
- miny = MAX2(miny, scissor->miny);
- maxx = MIN2(maxx, scissor->maxx);
- maxy = MIN2(maxy, scissor->maxy);
- }
-
- /* Special case for zero-area scissor.
- *
- * We can't allow the variables maxx and maxy to be zero because they are
- * subtracted from later in the code, which would cause emitting ~0 and
- * making the kernel checker angry.
- *
- * Let's consider we change maxx and maxy to 1, which is effectively
- * a one-pixel area. We must then change minx and miny to a number which is
- * greater than 1 to get the zero area back. */
- if (!maxx || !maxy) {
- minx = 2;
- miny = 2;
- maxx = 1;
- maxy = 1;
- }
-
- if (r300screen->caps->is_r500) {
- top_left =
- (minx << R300_SCISSORS_X_SHIFT) |
- (miny << R300_SCISSORS_Y_SHIFT);
- bottom_right =
- ((maxx - 1) << R300_SCISSORS_X_SHIFT) |
- ((maxy - 1) << R300_SCISSORS_Y_SHIFT);
+ BEGIN_CS(size);
+ OUT_CS_REG_SEQ(R300_SC_CLIPRECT_TL_0, 2);
+ if (r300->screen->caps.is_r500) {
+ OUT_CS((scissor->minx << R300_CLIPRECT_X_SHIFT) |
+ (scissor->miny << R300_CLIPRECT_Y_SHIFT));
+ OUT_CS(((scissor->maxx - 1) << R300_CLIPRECT_X_SHIFT) |
+ ((scissor->maxy - 1) << R300_CLIPRECT_Y_SHIFT));
} else {
- /* Offset of 1440 in non-R500 chipsets. */
- top_left =
- ((minx + 1440) << R300_SCISSORS_X_SHIFT) |
- ((miny + 1440) << R300_SCISSORS_Y_SHIFT);
- bottom_right =
- (((maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) |
- (((maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT);
+ OUT_CS(((scissor->minx + 1440) << R300_CLIPRECT_X_SHIFT) |
+ ((scissor->miny + 1440) << R300_CLIPRECT_Y_SHIFT));
+ OUT_CS(((scissor->maxx + 1440-1) << R300_CLIPRECT_X_SHIFT) |
+ ((scissor->maxy + 1440-1) << R300_CLIPRECT_Y_SHIFT));
}
-
- BEGIN_CS(size);
- OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
- OUT_CS(top_left);
- OUT_CS(bottom_right);
END_CS;
}
@@ -737,18 +805,19 @@ void r300_emit_textures_state(struct r300_context *r300,
if ((1 << i) & allstate->tx_enable) {
texstate = &allstate->regs[i];
- OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter[0]);
- OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter[1]);
+ OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter0);
+ OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter1);
OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (i * 4),
texstate->border_color);
- OUT_CS_REG(R300_TX_FORMAT0_0 + (i * 4), texstate->format[0]);
- OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format[1]);
- OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format[2]);
+ OUT_CS_REG(R300_TX_FORMAT0_0 + (i * 4), texstate->format.format0);
+ OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format.format1);
+ OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format.format2);
OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1);
- OUT_CS_RELOC(allstate->textures[i]->buffer, texstate->tile_config,
- RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ OUT_CS_TEX_RELOC(r300_texture(allstate->sampler_views[i]->base.texture),
+ texstate->format.tile_config,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0);
}
}
END_CS;
@@ -757,9 +826,9 @@ void r300_emit_textures_state(struct r300_context *r300,
void r300_emit_aos(struct r300_context* r300, unsigned offset)
{
struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer;
- struct pipe_vertex_element *velem = r300->vertex_element;
+ struct pipe_vertex_element *velem = r300->velems->velem;
int i;
- unsigned size1, size2, aos_count = r300->vertex_element_count;
+ unsigned size1, size2, aos_count = r300->velems->count;
unsigned packet_size = (aos_count * 3 + 1) / 2;
CS_LOCALS(r300);
@@ -788,12 +857,36 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset)
}
for (i = 0; i < aos_count; i++) {
- OUT_CS_RELOC_NO_OFFSET(vbuf[velem[i].vertex_buffer_index].buffer,
- RADEON_GEM_DOMAIN_GTT, 0, 0);
+ OUT_CS_BUF_RELOC_NO_OFFSET(vbuf[velem[i].vertex_buffer_index].buffer,
+ RADEON_GEM_DOMAIN_GTT, 0, 0);
}
END_CS;
}
+void r300_emit_vertex_buffer(struct r300_context* r300)
+{
+ CS_LOCALS(r300);
+
+ DBG(r300, DBG_DRAW, "r300: Preparing vertex buffer %p for render, "
+ "vertex size %d\n", r300->vbo,
+ r300->vertex_info.size);
+ /* Set the pointer to our vertex buffer. The emitted values are this:
+ * PACKET3 [3D_LOAD_VBPNTR]
+ * COUNT [1]
+ * FORMAT [size | stride << 8]
+ * OFFSET [offset into BO]
+ * VBPNTR [relocated BO]
+ */
+ BEGIN_CS(7);
+ OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3);
+ OUT_CS(1);
+ OUT_CS(r300->vertex_info.size |
+ (r300->vertex_info.size << 8));
+ OUT_CS(r300->vbo_offset);
+ OUT_CS_BUF_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ END_CS;
+}
+
void r300_emit_vertex_stream_state(struct r300_context* r300,
unsigned size, void* state)
{
@@ -852,11 +945,11 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state)
{
struct r300_vertex_shader* vs = (struct r300_vertex_shader*)state;
struct r300_vertex_program_code* code = &vs->code;
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ struct r300_screen* r300screen = r300->screen;
unsigned instruction_count = code->length / 4;
unsigned i;
- unsigned vtx_mem_size = r300screen->caps->is_r500 ? 128 : 72;
+ unsigned vtx_mem_size = r300screen->caps.is_r500 ? 128 : 72;
unsigned input_count = MAX2(util_bitcount(code->InputsRead), 1);
unsigned output_count = MAX2(util_bitcount(code->OutputsWritten), 1);
unsigned temp_count = MAX2(code->num_temporaries, 1);
@@ -865,13 +958,11 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state)
vtx_mem_size / output_count, 10);
unsigned pvs_num_controllers = MIN2(vtx_mem_size / temp_count, 6);
- CS_LOCALS(r300);
+ unsigned imm_first = vs->externals_count;
+ unsigned imm_end = vs->code.constants.Count;
+ unsigned imm_count = vs->immediates_count;
- if (!r300screen->caps->has_tcl) {
- debug_printf("r300: Implementation error: emit_vertex_shader called,"
- " but has_tcl is FALSE!\n");
- return;
- }
+ CS_LOCALS(r300);
BEGIN_CS(size);
/* R300_VAP_PVS_CODE_CNTL_0
@@ -893,37 +984,47 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state)
OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(pvs_num_slots) |
R300_PVS_NUM_CNTLRS(pvs_num_controllers) |
- R300_PVS_NUM_FPUS(r300screen->caps->num_vert_fpus) |
+ R300_PVS_NUM_FPUS(r300screen->caps.num_vert_fpus) |
R300_PVS_VF_MAX_VTX_NUM(12) |
- (r300screen->caps->is_r500 ? R500_TCL_STATE_OPTIMIZATION : 0));
+ (r300screen->caps.is_r500 ? R500_TCL_STATE_OPTIMIZATION : 0));
+
+ /* Emit immediates. */
+ if (imm_count) {
+ OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG,
+ (r300->screen->caps.is_r500 ?
+ R500_PVS_CONST_START : R300_PVS_CONST_START) +
+ imm_first);
+ OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, imm_count * 4);
+ for (i = imm_first; i < imm_end; i++) {
+ const float *data = vs->code.constants.Constants[i].u.Immediate;
+ OUT_CS_32F(data[0]);
+ OUT_CS_32F(data[1]);
+ OUT_CS_32F(data[2]);
+ OUT_CS_32F(data[3]);
+ }
+ }
END_CS;
}
-void r300_emit_vs_constant_buffer(struct r300_context* r300,
- struct rc_constant_list* constants)
+void r300_emit_vs_constants(struct r300_context* r300,
+ unsigned size, void *state)
{
- int i;
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ unsigned i;
+ unsigned count =
+ ((struct r300_vertex_shader*)r300->vs_state.state)->externals_count;
+ struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state;
CS_LOCALS(r300);
- if (!r300screen->caps->has_tcl) {
- debug_printf("r300: Implementation error: emit_vertex_shader called,"
- " but has_tcl is FALSE!\n");
- return;
- }
-
- if (constants->Count == 0)
+ if (!count)
return;
- BEGIN_CS(constants->Count * 4 + 3);
+ BEGIN_CS(size);
OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG,
- (r300screen->caps->is_r500 ?
+ (r300->screen->caps.is_r500 ?
R500_PVS_CONST_START : R300_PVS_CONST_START));
- OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, constants->Count * 4);
- for (i = 0; i < constants->Count; i++) {
- const float * data = get_shader_constant(r300,
- &constants->Constants[i],
- &r300->shader_constants[PIPE_SHADER_VERTEX]);
+ OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, count * 4);
+ for (i = 0; i < count; i++) {
+ const float *data = buf->constants[i];
OUT_CS_32F(data[0]);
OUT_CS_32F(data[1]);
OUT_CS_32F(data[2]);
@@ -972,7 +1073,7 @@ void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, voi
void r300_emit_buffer_validate(struct r300_context *r300,
boolean do_validate_vertex_buffers,
- struct pipe_buffer *index_buffer)
+ struct pipe_resource *index_buffer)
{
struct pipe_framebuffer_state* fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
@@ -980,89 +1081,96 @@ void r300_emit_buffer_validate(struct r300_context *r300,
(struct r300_textures_state*)r300->textures_state.state;
struct r300_texture* tex;
struct pipe_vertex_buffer *vbuf = r300->vertex_buffer;
- struct pipe_vertex_element *velem = r300->vertex_element;
- struct pipe_buffer *pbuf;
+ struct pipe_vertex_element *velem = r300->velems->velem;
+ struct pipe_resource *pbuf;
unsigned i;
boolean invalid = FALSE;
+ /* upload buffers first */
+ if (r300->any_user_vbs) {
+ r300_upload_user_buffers(r300);
+ r300->any_user_vbs = false;
+ }
+
/* Clean out BOs. */
- r300->winsys->reset_bos(r300->winsys);
+ r300->rws->reset_bos(r300->rws);
validate:
/* Color buffers... */
for (i = 0; i < fb->nr_cbufs; i++) {
- tex = (struct r300_texture*)fb->cbufs[i]->texture;
+ tex = r300_texture(fb->cbufs[i]->texture);
assert(tex && tex->buffer && "cbuf is marked, but NULL!");
- if (!r300->winsys->add_buffer(r300->winsys, tex->buffer,
- 0, RADEON_GEM_DOMAIN_VRAM)) {
+ if (!r300_add_texture(r300->rws, tex,
+ 0, RADEON_GEM_DOMAIN_VRAM)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
}
/* ...depth buffer... */
if (fb->zsbuf) {
- tex = (struct r300_texture*)fb->zsbuf->texture;
+ tex = r300_texture(fb->zsbuf->texture);
assert(tex && tex->buffer && "zsbuf is marked, but NULL!");
- if (!r300->winsys->add_buffer(r300->winsys, tex->buffer,
- 0, RADEON_GEM_DOMAIN_VRAM)) {
+ if (!r300_add_texture(r300->rws, tex,
+ 0, RADEON_GEM_DOMAIN_VRAM)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
}
/* ...textures... */
for (i = 0; i < texstate->count; i++) {
- tex = texstate->textures[i];
- if (!tex || !texstate->sampler_states[i])
+ if (!(texstate->tx_enable & (1 << i))) {
continue;
- if (!r300->winsys->add_buffer(r300->winsys, tex->buffer,
- RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) {
+ }
+
+ tex = r300_texture(texstate->sampler_views[i]->base.texture);
+ if (!r300_add_texture(r300->rws, tex,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
}
/* ...occlusion query buffer... */
- if (r300->dirty_state & R300_NEW_QUERY) {
- if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo,
- 0, RADEON_GEM_DOMAIN_GTT)) {
+ if (r300->query_start.dirty) {
+ if (!r300_add_buffer(r300->rws, r300->oqbo,
+ 0, RADEON_GEM_DOMAIN_GTT)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
}
/* ...vertex buffer for SWTCL path... */
if (r300->vbo) {
- if (!r300->winsys->add_buffer(r300->winsys, r300->vbo,
- RADEON_GEM_DOMAIN_GTT, 0)) {
+ if (!r300_add_buffer(r300->rws, r300->vbo,
+ RADEON_GEM_DOMAIN_GTT, 0)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
}
/* ...vertex buffers for HWTCL path... */
if (do_validate_vertex_buffers) {
- for (i = 0; i < r300->vertex_element_count; i++) {
+ for (i = 0; i < r300->velems->count; i++) {
pbuf = vbuf[velem[i].vertex_buffer_index].buffer;
- if (!r300->winsys->add_buffer(r300->winsys, pbuf,
- RADEON_GEM_DOMAIN_GTT, 0)) {
- r300->context.flush(&r300->context, 0, NULL);
+ if (!r300_add_buffer(r300->rws, pbuf,
+ RADEON_GEM_DOMAIN_GTT, 0)) {
+ r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
}
}
/* ...and index buffer for HWTCL path. */
if (index_buffer) {
- if (!r300->winsys->add_buffer(r300->winsys, index_buffer,
- RADEON_GEM_DOMAIN_GTT, 0)) {
+ if (!r300_add_buffer(r300->rws, index_buffer,
+ RADEON_GEM_DOMAIN_GTT, 0)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
}
-
- if (!r300->winsys->validate(r300->winsys)) {
+ if (!r300->rws->validate(r300->rws)) {
r300->context.flush(&r300->context, 0, NULL);
if (invalid) {
/* Well, hell. */
- debug_printf("r300: Stuck in validation loop, gonna quit now.");
- exit(1);
+ fprintf(stderr, "r300: Stuck in validation loop, gonna quit now.\n");
+ abort();
}
invalid = TRUE;
goto validate;
@@ -1075,68 +1183,31 @@ unsigned r300_get_num_dirty_dwords(struct r300_context *r300)
unsigned dwords = 0;
foreach(atom, &r300->atom_list) {
- if (atom->dirty || atom->always_dirty) {
+ if (atom->dirty) {
dwords += atom->size;
}
}
- /* XXX This is the compensation for the non-atomized states. */
- dwords += 1024;
-
return dwords;
}
/* Emit all dirty state. */
void r300_emit_dirty_state(struct r300_context* r300)
{
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ struct r300_screen* r300screen = r300->screen;
struct r300_atom* atom;
- if (r300->dirty_state & R300_NEW_QUERY) {
- r300_emit_query_start(r300);
- r300->dirty_state &= ~R300_NEW_QUERY;
- }
-
foreach(atom, &r300->atom_list) {
- if (atom->dirty || atom->always_dirty) {
+ if (atom->dirty) {
atom->emit(r300, atom->size, atom->state);
atom->dirty = FALSE;
}
}
- if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) {
- r300_emit_fragment_depth_config(r300, r300->fs);
- if (r300screen->caps->is_r500) {
- r500_emit_fragment_program_code(r300, &r300->fs->shader->code);
- } else {
- r300_emit_fragment_program_code(r300, &r300->fs->shader->code);
- }
- r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER;
+ /* Emit the VBO for SWTCL. */
+ if (!r300screen->caps.has_tcl) {
+ r300_emit_vertex_buffer(r300);
}
- if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER_CONSTANTS) {
- if (r300screen->caps->is_r500) {
- r500_emit_fs_constant_buffer(r300,
- &r300->fs->shader->code.constants);
- } else {
- r300_emit_fs_constant_buffer(r300,
- &r300->fs->shader->code.constants);
- }
- r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER_CONSTANTS;
- }
-
- if (r300->dirty_state & R300_NEW_VERTEX_SHADER_CONSTANTS) {
- struct r300_vertex_shader* vs = r300->vs_state.state;
- r300_emit_vs_constant_buffer(r300, &vs->code.constants);
- r300->dirty_state &= ~R300_NEW_VERTEX_SHADER_CONSTANTS;
- }
-
- /* XXX
- assert(r300->dirty_state == 0);
- */
-
- /* Finally, emit the VBO. */
- /* r300_emit_vertex_buffer(r300); */
-
r300->dirty_hw++;
}
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 449e640a88..56f7318cdb 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -43,22 +43,25 @@ void r300_emit_clip_state(struct r300_context* r300,
void r300_emit_dsa_state(struct r300_context* r300,
unsigned size, void* state);
-void r300_emit_fragment_program_code(struct r300_context* r300,
- struct rX00_fragment_program_code* generic_code);
+unsigned r300_get_fs_atom_size(struct r300_context *r300);
-void r300_emit_fs_constant_buffer(struct r300_context* r300,
- struct rc_constant_list* constants);
+void r300_emit_fs(struct r300_context* r300, unsigned size, void *state);
-void r500_emit_fragment_program_code(struct r300_context* r300,
- struct rX00_fragment_program_code* generic_code);
+void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state);
-void r500_emit_fs_constant_buffer(struct r300_context* r300,
- struct rc_constant_list* constants);
+void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state);
+
+unsigned r500_get_fs_atom_size(struct r300_context *r300);
+
+void r500_emit_fs(struct r300_context* r300, unsigned size, void *state);
+
+void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state);
+
+void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state);
void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state);
-void r300_emit_query_begin(struct r300_context* r300,
- struct r300_query* query);
+void r300_emit_query_start(struct r300_context *r300, unsigned size, void *state);
void r300_emit_query_end(struct r300_context* r300);
@@ -81,8 +84,8 @@ void r300_emit_vertex_stream_state(struct r300_context* r300,
void r300_emit_vap_output_state(struct r300_context* r300,
unsigned size, void* state);
-void r300_emit_vs_constant_buffer(struct r300_context* r300,
- struct rc_constant_list* constants);
+void r300_emit_vs_constants(struct r300_context* r300,
+ unsigned size, void *state);
void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state);
@@ -103,6 +106,6 @@ void r300_emit_dirty_state(struct r300_context* r300);
void r300_emit_buffer_validate(struct r300_context *r300,
boolean do_validate_vertex_buffers,
- struct pipe_buffer *index_buffer);
+ struct pipe_resource *index_buffer);
#endif /* R300_EMIT_H */
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index e37d309270..e78c6a3624 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -52,7 +52,6 @@ static void r300_flush(struct pipe_context* pipe,
if (r300->dirty_hw) {
FLUSH_CS;
- r300->dirty_state = R300_NEW_KITCHEN_SINK;
r300->dirty_hw = 0;
/* New kitchen sink, baby. */
@@ -61,6 +60,12 @@ static void r300_flush(struct pipe_context* pipe,
atom->dirty = TRUE;
}
}
+
+ /* Unmark HWTCL state for SWTCL. */
+ if (!r300->screen->caps.has_tcl) {
+ r300->vs_state.dirty = FALSE;
+ r300->vs_constants.dirty = FALSE;
+ }
}
/* reset flushed query */
@@ -69,7 +74,6 @@ static void r300_flush(struct pipe_context* pipe,
}
}
-
void r300_init_flush_functions(struct r300_context* r300)
{
r300->context.flush = r300_flush;
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c
index 3c2625269b..4d61f63853 100644
--- a/src/gallium/drivers/r300/r300_fs.c
+++ b/src/gallium/drivers/r300/r300_fs.c
@@ -26,10 +26,12 @@
#include "util/u_memory.h"
#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_ureg.h"
#include "r300_context.h"
#include "r300_screen.h"
#include "r300_fs.h"
+#include "r300_reg.h"
#include "r300_tgsi_to_rc.h"
#include "radeon_code.h"
@@ -69,26 +71,27 @@ void r300_shader_read_fs_inputs(struct tgsi_shader_info* info,
break;
default:
- assert(0);
+ fprintf(stderr, "r300: FP: Unknown input semantic: %i\n",
+ info->input_semantic_name[i]);
}
}
}
static void find_output_registers(struct r300_fragment_program_compiler * compiler,
- struct r300_fragment_shader * fs)
+ struct r300_fragment_shader_code *shader)
{
unsigned i, colorbuf_count = 0;
/* Mark the outputs as not present initially */
- compiler->OutputColor[0] = fs->info.num_outputs;
- compiler->OutputColor[1] = fs->info.num_outputs;
- compiler->OutputColor[2] = fs->info.num_outputs;
- compiler->OutputColor[3] = fs->info.num_outputs;
- compiler->OutputDepth = fs->info.num_outputs;
+ compiler->OutputColor[0] = shader->info.num_outputs;
+ compiler->OutputColor[1] = shader->info.num_outputs;
+ compiler->OutputColor[2] = shader->info.num_outputs;
+ compiler->OutputColor[3] = shader->info.num_outputs;
+ compiler->OutputDepth = shader->info.num_outputs;
/* Now see where they really are. */
- for(i = 0; i < fs->info.num_outputs; ++i) {
- switch(fs->info.output_semantic_name[i]) {
+ for(i = 0; i < shader->info.num_outputs; ++i) {
+ switch(shader->info.output_semantic_name[i]) {
case TGSI_SEMANTIC_COLOR:
compiler->OutputColor[colorbuf_count] = i;
colorbuf_count++;
@@ -128,20 +131,21 @@ static void allocate_hardware_inputs(
}
}
-static void get_compare_state(
+static void get_external_state(
struct r300_context* r300,
- struct r300_fragment_program_external_state* state,
- unsigned shadow_samplers)
+ struct r300_fragment_program_external_state* state)
{
- struct r300_textures_state *texstate =
- (struct r300_textures_state*)r300->textures_state.state;
-
- memset(state, 0, sizeof(*state));
+ struct r300_textures_state *texstate = r300->textures_state.state;
+ unsigned i;
- for (int i = 0; i < texstate->sampler_count; i++) {
+ for (i = 0; i < texstate->sampler_state_count; i++) {
struct r300_sampler_state* s = texstate->sampler_states[i];
- if (s && s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ if (!s) {
+ continue;
+ }
+
+ if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
/* XXX Gallium doesn't provide us with any information regarding
* this mode, so we are screwed. I'm setting 0 = LUMINANCE. */
state->unit[i].depth_texture_mode = 0;
@@ -149,17 +153,86 @@ static void get_compare_state(
/* Fortunately, no need to translate this. */
state->unit[i].texture_compare_func = s->state.compare_func;
}
+
+ state->unit[i].non_normalized_coords = !s->state.normalized_coords;
+
+ if (texstate->sampler_views[i]) {
+ struct r300_texture *t;
+ t = (struct r300_texture*)texstate->sampler_views[i]->base.texture;
+
+ /* XXX this should probably take into account STR, not just S. */
+ if (t->uses_pitch) {
+ switch (s->state.wrap_s) {
+ case PIPE_TEX_WRAP_REPEAT:
+ state->unit[i].wrap_mode = RC_WRAP_REPEAT;
+ state->unit[i].fake_npot = TRUE;
+ break;
+
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ state->unit[i].wrap_mode = RC_WRAP_MIRRORED_REPEAT;
+ state->unit[i].fake_npot = TRUE;
+ break;
+
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ state->unit[i].wrap_mode = RC_WRAP_MIRRORED_CLAMP;
+ state->unit[i].fake_npot = TRUE;
+ break;
+
+ default:
+ state->unit[i].wrap_mode = RC_WRAP_NONE;
+ break;
+ }
+ }
+ }
}
}
static void r300_translate_fragment_shader(
struct r300_context* r300,
+ struct r300_fragment_shader_code* shader,
+ const struct tgsi_token *tokens);
+
+static void r300_dummy_fragment_shader(
+ struct r300_context* r300,
struct r300_fragment_shader_code* shader)
{
- struct r300_fragment_shader* fs = r300->fs;
+ struct pipe_shader_state state;
+ struct ureg_program *ureg;
+ struct ureg_dst out;
+ struct ureg_src imm;
+
+ /* Make a simple fragment shader which outputs (0, 0, 0, 1) */
+ ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+ out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+ imm = ureg_imm4f(ureg, 0, 0, 0, 1);
+
+ ureg_MOV(ureg, out, imm);
+ ureg_END(ureg);
+
+ state.tokens = ureg_finalize(ureg);
+
+ shader->dummy = TRUE;
+ r300_translate_fragment_shader(r300, shader, state.tokens);
+
+ ureg_destroy(ureg);
+}
+
+static void r300_translate_fragment_shader(
+ struct r300_context* r300,
+ struct r300_fragment_shader_code* shader,
+ const struct tgsi_token *tokens)
+{
struct r300_fragment_program_compiler compiler;
struct tgsi_to_rc ttr;
- int wpos = fs->inputs.wpos;
+ int wpos;
+ unsigned i;
+
+ tgsi_scan_shader(tokens, &shader->info);
+ r300_shader_read_fs_inputs(&shader->info, &shader->inputs);
+
+ wpos = shader->inputs.wpos;
/* Setup the compiler. */
memset(&compiler, 0, sizeof(compiler));
@@ -168,25 +241,24 @@ static void r300_translate_fragment_shader(
compiler.code = &shader->code;
compiler.state = shader->compare_state;
- compiler.is_r500 = r300_screen(r300->context.screen)->caps->is_r500;
+ compiler.is_r500 = r300->screen->caps.is_r500;
+ compiler.max_temp_regs = compiler.is_r500 ? 128 : 32;
compiler.AllocateHwInputs = &allocate_hardware_inputs;
- compiler.UserData = &fs->inputs;
+ compiler.UserData = &shader->inputs;
- find_output_registers(&compiler, fs);
+ find_output_registers(&compiler, shader);
if (compiler.Base.Debug) {
debug_printf("r300: Initial fragment program\n");
- tgsi_dump(fs->state.tokens, 0);
+ tgsi_dump(tokens, 0);
}
/* Translate TGSI to our internal representation */
ttr.compiler = &compiler.Base;
- ttr.info = &fs->info;
+ ttr.info = &shader->info;
ttr.use_half_swizzles = TRUE;
- r300_tgsi_to_rc(&ttr, fs->state.tokens);
-
- fs->shadow_samplers = compiler.Base.Program.ShadowSamplers;
+ r300_tgsi_to_rc(&ttr, tokens);
/**
* Transform the program to support WPOS.
@@ -202,11 +274,47 @@ static void r300_translate_fragment_shader(
/* Invoke the compiler */
r3xx_compile_fragment_program(&compiler);
+
if (compiler.Base.Error) {
- /* XXX failover maybe? */
- DBG(r300, DBG_FP, "r300: Error compiling fragment program: %s\n",
- compiler.Base.ErrorMsg);
- assert(0);
+ fprintf(stderr, "r300 FP: Compiler Error:\n%sUsing a dummy shader"
+ " instead.\n", compiler.Base.ErrorMsg);
+
+ if (shader->dummy) {
+ fprintf(stderr, "r300 FP: Cannot compile the dummy shader! "
+ "Giving up...\n");
+ abort();
+ }
+
+ rc_destroy(&compiler.Base);
+ r300_dummy_fragment_shader(r300, shader);
+ return;
+ }
+
+ /* Initialize numbers of constants for each type. */
+ shader->externals_count = ttr.immediate_offset;
+ shader->immediates_count = 0;
+ shader->rc_state_count = 0;
+
+ for (i = shader->externals_count; i < shader->code.constants.Count; i++) {
+ switch (shader->code.constants.Constants[i].Type) {
+ case RC_CONSTANT_IMMEDIATE:
+ ++shader->immediates_count;
+ break;
+ case RC_CONSTANT_STATE:
+ ++shader->rc_state_count;
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ /* Setup shader depth output. */
+ if (shader->code.writes_depth) {
+ shader->fg_depth_src = R300_FG_DEPTH_SRC_SHADER;
+ shader->us_out_w = R300_W_FMT_W24 | R300_W_SRC_US;
+ } else {
+ shader->fg_depth_src = R300_FG_DEPTH_SRC_SCAN;
+ shader->us_out_w = R300_W_FMT_W0 | R300_W_SRC_US;
}
/* And, finally... */
@@ -215,24 +323,22 @@ static void r300_translate_fragment_shader(
boolean r300_pick_fragment_shader(struct r300_context* r300)
{
- struct r300_fragment_shader* fs = r300->fs;
- struct r300_fragment_program_external_state state;
+ struct r300_fragment_shader* fs = r300_fs(r300);
+ struct r300_fragment_program_external_state state = {{{ 0 }}};
struct r300_fragment_shader_code* ptr;
+ get_external_state(r300, &state);
+
if (!fs->first) {
/* Build the fragment shader for the first time. */
fs->first = fs->shader = CALLOC_STRUCT(r300_fragment_shader_code);
- /* BTW shadow samplers will be known after the first translation,
- * therefore we set ~0, which means it should look at all sampler
- * states. This choice doesn't have any impact on the correctness. */
- get_compare_state(r300, &fs->shader->compare_state, ~0);
- r300_translate_fragment_shader(r300, fs->shader);
+ memcpy(&fs->shader->compare_state, &state,
+ sizeof(struct r300_fragment_program_external_state));
+ r300_translate_fragment_shader(r300, fs->shader, fs->state.tokens);
return TRUE;
- } else if (fs->shadow_samplers) {
- get_compare_state(r300, &state, fs->shadow_samplers);
-
+ } else {
/* Check if the currently-bound shader has been compiled
* with the texture-compare state we need. */
if (memcmp(&fs->shader->compare_state, &state, sizeof(state)) != 0) {
@@ -240,8 +346,12 @@ boolean r300_pick_fragment_shader(struct r300_context* r300)
ptr = fs->first;
while (ptr) {
if (memcmp(&ptr->compare_state, &state, sizeof(state)) == 0) {
- fs->shader = ptr;
- return TRUE;
+ if (fs->shader != ptr) {
+ fs->shader = ptr;
+ return TRUE;
+ }
+ /* The currently-bound one is OK. */
+ return FALSE;
}
ptr = ptr->next;
}
@@ -252,7 +362,7 @@ boolean r300_pick_fragment_shader(struct r300_context* r300)
fs->first = fs->shader = ptr;
ptr->compare_state = state;
- r300_translate_fragment_shader(r300, ptr);
+ r300_translate_fragment_shader(r300, ptr, fs->state.tokens);
return TRUE;
}
}
diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h
index 40ce874353..1cc4355359 100644
--- a/src/gallium/drivers/r300/r300_fs.h
+++ b/src/gallium/drivers/r300/r300_fs.h
@@ -31,6 +31,22 @@
#include "r300_shader_semantics.h"
struct r300_fragment_shader_code {
+ struct tgsi_shader_info info;
+ struct r300_shader_semantics inputs;
+
+ /* Whether the shader was replaced by a dummy one due to a shader
+ * compilation failure. */
+ boolean dummy;
+
+ /* Numbers of constants for each type. */
+ unsigned externals_count;
+ unsigned immediates_count;
+ unsigned rc_state_count;
+
+ /* Registers for fragment depth output setup. */
+ uint32_t fg_depth_src; /* R300_FG_DEPTH_SRC: 0x4bd8 */
+ uint32_t us_out_w; /* R300_US_W_FMT: 0x46b4 */
+
struct r300_fragment_program_external_state compare_state;
struct rX00_fragment_program_code code;
@@ -41,12 +57,6 @@ struct r300_fragment_shader {
/* Parent class */
struct pipe_shader_state state;
- struct tgsi_shader_info info;
- struct r300_shader_semantics inputs;
-
- /* Bits 0-15: TRUE if it's a shadow sampler, FALSE otherwise. */
- unsigned shadow_samplers;
-
/* Currently-bound fragment shader. */
struct r300_fragment_shader_code* shader;
diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c
index ca00b043c5..5c27796e89 100644
--- a/src/gallium/drivers/r300/r300_query.c
+++ b/src/gallium/drivers/r300/r300_query.c
@@ -25,16 +25,16 @@
#include "r300_context.h"
#include "r300_screen.h"
-#include "r300_cs.h"
#include "r300_emit.h"
#include "r300_query.h"
-#include "r300_reg.h"
+
+#include <stdio.h>
static struct pipe_query *r300_create_query(struct pipe_context *pipe,
unsigned query_type)
{
struct r300_context *r300 = r300_context(pipe);
- struct r300_screen *r300screen = r300_screen(r300->context.screen);
+ struct r300_screen *r300screen = r300->screen;
unsigned query_size;
struct r300_query *q, *qptr;
@@ -45,10 +45,10 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe,
q->active = FALSE;
- if (r300screen->caps->family == CHIP_FAMILY_RV530)
- query_size = r300screen->caps->num_z_pipes * sizeof(uint32_t);
+ if (r300screen->caps.family == CHIP_FAMILY_RV530)
+ query_size = r300screen->caps.num_z_pipes * sizeof(uint32_t);
else
- query_size = r300screen->caps->num_frag_pipes * sizeof(uint32_t);
+ query_size = r300screen->caps.num_frag_pipes * sizeof(uint32_t);
if (!is_empty_list(&r300->query_list)) {
qptr = last_elem(&r300->query_list);
@@ -76,29 +76,31 @@ static void r300_destroy_query(struct pipe_context* pipe,
static void r300_begin_query(struct pipe_context* pipe,
struct pipe_query* query)
{
- uint32_t* map;
+ uint32_t value = ~0U;
struct r300_context* r300 = r300_context(pipe);
struct r300_query* q = (struct r300_query*)query;
assert(r300->query_current == NULL);
- map = pipe->screen->buffer_map(pipe->screen, r300->oqbo,
- PIPE_BUFFER_USAGE_CPU_WRITE);
- map += q->offset / 4;
- *map = ~0U;
- pipe->screen->buffer_unmap(pipe->screen, r300->oqbo);
+ pipe_buffer_write(pipe,
+ r300->oqbo,
+ q->offset,
+ sizeof value,
+ &value);
q->flushed = FALSE;
r300->query_current = q;
- r300->dirty_state |= R300_NEW_QUERY;
+ r300->query_start.dirty = TRUE;
}
static void r300_end_query(struct pipe_context* pipe,
struct pipe_query* query)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_query* q = (struct r300_query*)query;
r300_emit_query_end(r300);
+ q->begin_emitted = false;
r300->query_current = NULL;
}
@@ -108,9 +110,10 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
uint64_t* result)
{
struct r300_context* r300 = r300_context(pipe);
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ struct r300_screen* r300screen = r300->screen;
struct r300_query *q = (struct r300_query*)query;
- unsigned flags = PIPE_BUFFER_USAGE_CPU_READ;
+ struct pipe_transfer *transfer;
+ unsigned flags = PIPE_TRANSFER_READ;
uint32_t* map;
uint32_t temp = 0;
unsigned i, num_results;
@@ -118,25 +121,25 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
if (q->flushed == FALSE)
pipe->flush(pipe, 0, NULL);
if (!wait) {
- flags |= PIPE_BUFFER_USAGE_DONTBLOCK;
+ flags |= PIPE_TRANSFER_DONTBLOCK;
}
- map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, flags);
+ map = pipe_buffer_map(pipe, r300->oqbo, flags, &transfer);
if (!map)
return FALSE;
map += q->offset / 4;
- if (r300screen->caps->family == CHIP_FAMILY_RV530)
- num_results = r300screen->caps->num_z_pipes;
+ if (r300screen->caps.family == CHIP_FAMILY_RV530)
+ num_results = r300screen->caps.num_z_pipes;
else
- num_results = r300screen->caps->num_frag_pipes;
+ num_results = r300screen->caps.num_frag_pipes;
for (i = 0; i < num_results; i++) {
if (*map == ~0U) {
/* Looks like our results aren't ready yet. */
if (wait) {
- debug_printf("r300: Despite waiting, OQ results haven't"
- " come in yet.\n");
+ fprintf(stderr, "r300: Despite waiting, OQ results haven't "
+ "come in yet.\n");
}
temp = ~0U;
break;
@@ -144,7 +147,7 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
temp += *map;
map++;
}
- pipe->screen->buffer_unmap(pipe->screen, r300->oqbo);
+ pipe_buffer_unmap(pipe, r300->oqbo, transfer);
if (temp == ~0U) {
/* Our results haven't been written yet... */
@@ -155,10 +158,33 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
return TRUE;
}
+static void r300_render_condition(struct pipe_context *pipe,
+ struct pipe_query *query,
+ uint mode)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ uint64_t result;
+ boolean wait;
+
+ if (query) {
+ wait = mode == PIPE_RENDER_COND_WAIT ||
+ mode == PIPE_RENDER_COND_BY_REGION_WAIT;
+
+ if (!r300_get_query_result(pipe, query, wait, &result)) {
+ r300->skip_rendering = FALSE;
+ }
+
+ r300->skip_rendering = result == 0;
+ } else {
+ r300->skip_rendering = FALSE;
+ }
+}
+
void r300_init_query_functions(struct r300_context* r300) {
r300->context.create_query = r300_create_query;
r300->context.destroy_query = r300_destroy_query;
r300->context.begin_query = r300_begin_query;
r300->context.end_query = r300_end_query;
r300->context.get_query_result = r300_get_query_result;
+ r300->context.render_condition = r300_render_condition;
}
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index c67cc86871..239f91443f 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -1500,6 +1500,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_ANISO_THRESHOLD_MASK (7<<17)
# define R500_MACRO_SWITCH (1<<22)
+# define R500_TX_MAX_ANISO(x) ((x) << 23)
+# define R500_TX_MAX_ANISO_MASK (63 << 23)
+# define R500_TX_ANISO_HIGH_QUALITY (1 << 30)
+
# define R500_BORDER_FIX (1<<31)
#define R300_TX_FORMAT0_0 0x4480
@@ -1539,7 +1543,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_TX_FORMAT_DXT1 0xF
# define R300_TX_FORMAT_DXT3 0x10
# define R300_TX_FORMAT_DXT5 0x11
-# define R300_TX_FORMAT_Y8 0x12
+# define R300_TX_FORMAT_CxV8U8 0x12
# define R300_TX_FORMAT_AVYU444 0x13
# define R300_TX_FORMAT_VYUY422 0x14
# define R300_TX_FORMAT_YVYU422 0x15
@@ -1552,6 +1556,26 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_TX_FORMAT_32F_32F 0x1C
# define R300_TX_FORMAT_32F_32F_32F_32F 0x1D
# define R300_TX_FORMAT_W24_FP 0x1E
+# define R400_TX_FORMAT_ATI2N 0x1F
+
+/* These need TX_FORMAT2_[0-15].TXFORMAT_MSB set.
+
+ My guess is the 10-bit formats are the 8-bit ones but with filtering being
+ performed with the precision of 10 bits per channel. This makes sense
+ with sRGB textures since the conversion to linear space reduces the precision
+ significantly so the shader gets approximately the 8-bit precision
+ in the end. It might also improve the quality of HDR rendering where
+ high-precision filtering is desirable.
+
+ Again, this is guessed, the formats might mean something entirely else.
+ The others should be fine. */
+# define R500_TX_FORMAT_X1 0x0
+# define R500_TX_FORMAT_X1_REV 0x1
+# define R500_TX_FORMAT_X10 0x2
+# define R500_TX_FORMAT_Y10X10 0x3
+# define R500_TX_FORMAT_W10Z10Y10X10 0x4
+# define R500_TX_FORMAT_ATI1N 0x5
+
# define R300_TX_FORMAT_SIGNED_W (1 << 5)
# define R300_TX_FORMAT_SIGNED_Z (1 << 6)
@@ -1716,6 +1740,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 13)
# define R300_PFS_CNTL_TEX_END_SHIFT 18
# define R300_PFS_CNTL_TEX_END_MASK (31 << 18)
+# define R400_PFS_CNTL_TEX_OFFSET_MSB_SHIFT 24
+# define R400_PFS_CNTL_TEX_OFFSET_MSB_MASK (0xf << 24)
+# define R400_PFS_CNTL_TEX_END_MSB_SHIFT 28
+# define R400_PFS_CNTL_TEX_END_MSB_MASK (0xf << 28)
/* gap */
@@ -1740,6 +1768,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_TEX_SIZE_MASK (31 << 17)
# define R300_RGBA_OUT (1 << 22)
# define R300_W_OUT (1 << 23)
+# define R400_TEX_START_MSB_SHIFT 24
+# define R400_TEX_START_MSG_MASK (0xf << 24)
+# define R400_TEX_SIZE_MSB_SHIFT 28
+# define R400_TEX_SIZE_MSG_MASK (0xf << 28)
/* TEX
* As far as I can tell, texture instructions cannot write into output
@@ -1760,6 +1792,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_TEX_OP_TXP 3
# define R300_TEX_OP_TXB 4
# define R300_TEX_INST_MASK (7 << 15)
+# define R400_SRC_ADDR_EXT_BIT (1 << 19)
+# define R400_DST_ADDR_EXT_BIT (1 << 20)
/* Output format from the unfied shader */
#define R300_US_OUT_FMT_0 0x46A4
@@ -2068,6 +2102,43 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_ALU_OUTA_CLAMP (1 << 30)
/* END: Fragment program instruction set */
+/* R4xx extended fragment shader registers. */
+#define R400_US_ALU_EXT_ADDR_0 0x4ac0 /* up to 63 (0x4bbc) */
+# define R400_ADDR0_EXT_RGB_MSB_BIT 0x01
+# define R400_ADDR1_EXT_RGB_MSB_BIT 0x02
+# define R400_ADDR2_EXT_RGB_MSB_BIT 0x04
+# define R400_ADDRD_EXT_RGB_MSB_BIT 0x08
+# define R400_ADDR0_EXT_A_MSB_BIT 0x10
+# define R400_ADDR1_EXT_A_MSB_BIT 0x20
+# define R400_ADDR2_EXT_A_MSB_BIT 0x40
+# define R400_ADDRD_EXT_A_MSB_BIT 0x80
+#define R400_US_CODE_BANK 0x46b8
+# define R400_BANK_SHIFT 0
+# define R400_BANK_MASK 0xf
+# define R400_R390_MODE_ENABLE (1 << 4)
+#define R400_US_CODE_EXT 0x46bc
+# define R400_ALU_OFFSET_MSB_SHIFT 0
+# define R400_ALU_OFFSET_MSB_MASK (0x7 << 0)
+# define R400_ALU_SIZE_MSB_SHIFT 3
+# define R400_ALU_SIZE_MSB_MASK (0x7 << 3)
+# define R400_ALU_START0_MSB_SHIFT 6
+# define R400_ALU_START0_MSB_MASK (0x7 << 6)
+# define R400_ALU_SIZE0_MSB_SHIFT 9
+# define R400_ALU_SIZE0_MSB_MASK (0x7 << 9)
+# define R400_ALU_START1_MSB_SHIFT 12
+# define R400_ALU_START1_MSB_MASK (0x7 << 12)
+# define R400_ALU_SIZE1_MSB_SHIFT 15
+# define R400_ALU_SIZE1_MSB_MASK (0x7 << 15)
+# define R400_ALU_START2_MSB_SHIFT 18
+# define R400_ALU_START2_MSB_MASK (0x7 << 18)
+# define R400_ALU_SIZE2_MSB_SHIFT 21
+# define R400_ALU_SIZE2_MSB_MASK (0x7 << 21)
+# define R400_ALU_START3_MSB_SHIFT 24
+# define R400_ALU_START3_MSB_MASK (0x7 << 24)
+# define R400_ALU_SIZE3_MSB_SHIFT 27
+# define R400_ALU_SIZE3_MSB_MASK (0x7 << 27)
+/* END: R4xx extended fragment shader registers. */
+
/* Fog: Fog Blending Enable */
#define R300_FG_FOG_BLEND 0x4bc0
# define R300_FG_FOG_BLEND_DISABLE (0 << 0)
@@ -3266,7 +3337,6 @@ enum {
# define R300_W_SRC_US (0 << 2)
# define R300_W_SRC_RAS (1 << 2)
-
/* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
* Two parameter dwords:
* 0. VAP_VTX_FMT: The first parameter is not written to hardware
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 6c891029a5..a3fd8cc67d 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -30,22 +30,21 @@
#include "util/u_format.h"
#include "util/u_memory.h"
+#include "util/u_upload_mgr.h"
#include "util/u_prim.h"
#include "r300_cs.h"
#include "r300_context.h"
+#include "r300_screen_buffer.h"
#include "r300_emit.h"
#include "r300_reg.h"
#include "r300_render.h"
#include "r300_state_derived.h"
-/* r300_render: Vertex and index buffer primitive emission. */
-#define R300_MAX_VBO_SIZE (1024 * 1024)
-
/* XXX The DRM rejects VAP_ALT_NUM_VERTICES.. */
//#define ENABLE_ALT_NUM_VERTS
-uint32_t r300_translate_primitive(unsigned prim)
+static uint32_t r300_translate_primitive(unsigned prim)
{
switch (prim) {
case PIPE_PRIM_POINTS:
@@ -123,7 +122,7 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300,
static boolean r300_reserve_cs_space(struct r300_context *r300,
unsigned dwords)
{
- if (!r300->winsys->check_cs(r300->winsys, dwords)) {
+ if (!r300->rws->check_cs(r300->rws, dwords)) {
r300->context.flush(&r300->context, 0, NULL);
return TRUE;
}
@@ -131,19 +130,53 @@ static boolean r300_reserve_cs_space(struct r300_context *r300,
}
static boolean immd_is_good_idea(struct r300_context *r300,
- unsigned count)
+ unsigned count)
{
- return count <= 4;
+ struct pipe_vertex_element* velem;
+ struct pipe_vertex_buffer* vbuf;
+ boolean checked[PIPE_MAX_ATTRIBS] = {0};
+ unsigned vertex_element_count = r300->velems->count;
+ unsigned i, vbi;
+
+ if (count > 10 || DBG_ON(r300, DBG_NO_IMMD)) {
+ return FALSE;
+ }
+
+ /* We shouldn't map buffers referenced by CS, busy buffers,
+ * and ones placed in VRAM. */
+ /* XXX Check for VRAM buffers. */
+ for (i = 0; i < vertex_element_count; i++) {
+ velem = &r300->velems->velem[i];
+ vbi = velem->vertex_buffer_index;
+
+ if (!checked[vbi]) {
+ vbuf = &r300->vertex_buffer[vbi];
+
+ if (r300_buffer_is_referenced(&r300->context,
+ vbuf->buffer,
+ R300_REF_CS | R300_REF_HW)) {
+ /* It's a very bad idea to map it... */
+ return FALSE;
+ }
+ checked[vbi] = TRUE;
+ }
+ }
+ return TRUE;
}
-static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
- unsigned mode,
- unsigned start,
- unsigned count)
+/*****************************************************************************
+ * The emission of draw packets for r500. Older GPUs may use these functions *
+ * after resolving fallback issues (e.g. stencil ref two-sided). *
+ ****************************************************************************/
+
+void r500_emit_draw_arrays_immediate(struct r300_context *r300,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
{
struct pipe_vertex_element* velem;
struct pipe_vertex_buffer* vbuf;
- unsigned vertex_element_count = r300->vertex_element_count;
+ unsigned vertex_element_count = r300->velems->count;
unsigned i, v, vbi, dw, elem_offset, dwords;
/* Size of the vertex, in dwords. */
@@ -161,12 +194,13 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
/* Mapped vertex buffers. */
uint32_t* map[PIPE_MAX_ATTRIBS] = {0};
+ struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {NULL};
CS_LOCALS(r300);
/* Calculate the vertex size, offsets, strides etc. and map the buffers. */
for (i = 0; i < vertex_element_count; i++) {
- velem = &r300->vertex_element[i];
+ velem = &r300->velems->velem[i];
offset[i] = velem->src_offset / 4;
size[i] = util_format_get_blocksize(velem->src_format) / 4;
vertex_size += size[i];
@@ -175,26 +209,28 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
/* Map the buffer. */
if (!map[vbi]) {
vbuf = &r300->vertex_buffer[vbi];
- map[vbi] = (uint32_t*)pipe_buffer_map(r300->context.screen,
+ map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context,
vbuf->buffer,
- PIPE_BUFFER_USAGE_CPU_READ);
+ PIPE_TRANSFER_READ,
+ &transfer[vbi]);
map[vbi] += vbuf->buffer_offset / 4;
stride[vbi] = vbuf->stride / 4;
}
}
- dwords = 10 + count * vertex_size;
+ dwords = 9 + count * vertex_size;
r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords);
- r300_emit_buffer_validate(r300, FALSE, 0);
+ r300_emit_buffer_validate(r300, FALSE, NULL);
r300_emit_dirty_state(r300);
BEGIN_CS(dwords);
OUT_CS_REG(R300_GA_COLOR_CONTROL,
r300_provoking_vertex_fixes(r300, mode));
OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
- OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0);
- OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1);
+ OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
+ OUT_CS(count - 1);
+ OUT_CS(0);
OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size);
OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) |
r300_translate_primitive(mode));
@@ -202,7 +238,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
/* Emit vertices. */
for (v = 0; v < count; v++) {
for (i = 0; i < vertex_element_count; i++) {
- velem = &r300->vertex_element[i];
+ velem = &r300->velems->velem[i];
vbi = velem->vertex_buffer_index;
elem_offset = offset[i] + stride[vbi] * (v + start);
@@ -215,19 +251,19 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
/* Unmap buffers. */
for (i = 0; i < vertex_element_count; i++) {
- vbi = r300->vertex_element[i].vertex_buffer_index;
+ vbi = r300->velems->velem[i].vertex_buffer_index;
if (map[vbi]) {
vbuf = &r300->vertex_buffer[vbi];
- pipe_buffer_unmap(r300->context.screen, vbuf->buffer);
+ pipe_buffer_unmap(&r300->context, vbuf->buffer, transfer[vbi]);
map[vbi] = NULL;
}
}
}
-static void r300_emit_draw_arrays(struct r300_context *r300,
- unsigned mode,
- unsigned count)
+void r500_emit_draw_arrays(struct r300_context *r300,
+ unsigned mode,
+ unsigned count)
{
#if defined(ENABLE_ALT_NUM_VERTS)
boolean alt_num_verts = count > 65535;
@@ -237,16 +273,21 @@ static void r300_emit_draw_arrays(struct r300_context *r300,
CS_LOCALS(r300);
if (alt_num_verts) {
- assert(count < (1 << 24));
- BEGIN_CS(10);
+ if (count >= (1 << 24)) {
+ fprintf(stderr, "r300: Got a huge number of vertices: %i, "
+ "refusing to render.\n", count);
+ return;
+ }
+ BEGIN_CS(9);
OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count);
} else {
- BEGIN_CS(8);
+ BEGIN_CS(7);
}
OUT_CS_REG(R300_GA_COLOR_CONTROL,
r300_provoking_vertex_fixes(r300, mode));
- OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0);
- OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1);
+ OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
+ OUT_CS(count - 1);
+ OUT_CS(0);
OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) |
r300_translate_primitive(mode) |
@@ -254,14 +295,14 @@ static void r300_emit_draw_arrays(struct r300_context *r300,
END_CS;
}
-static void r300_emit_draw_elements(struct r300_context *r300,
- struct pipe_buffer* indexBuffer,
- unsigned indexSize,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count)
+void r500_emit_draw_elements(struct r300_context *r300,
+ struct pipe_resource* indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
{
uint32_t count_dwords;
uint32_t offset_dwords = indexSize * start / sizeof(uint32_t);
@@ -272,24 +313,28 @@ static void r300_emit_draw_elements(struct r300_context *r300,
#endif
CS_LOCALS(r300);
- assert((start * indexSize) % 4 == 0);
- assert(count < (1 << 24));
+ if (count >= (1 << 24)) {
+ fprintf(stderr, "r300: Got a huge number of vertices: %i, "
+ "refusing to render.\n", count);
+ return;
+ }
+
+ maxIndex = MIN2(maxIndex, r300->vertex_buffer_max_index);
DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n",
count, minIndex, maxIndex);
- maxIndex = MIN2(maxIndex, ((1 << 24) - 1));
-
if (alt_num_verts) {
- BEGIN_CS(16);
+ BEGIN_CS(15);
OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count);
} else {
- BEGIN_CS(14);
+ BEGIN_CS(13);
}
OUT_CS_REG(R300_GA_COLOR_CONTROL,
r300_provoking_vertex_fixes(r300, mode));
- OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, minIndex);
- OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, maxIndex);
+ OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
+ OUT_CS(maxIndex);
+ OUT_CS(minIndex);
OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0);
if (indexSize == 4) {
count_dwords = count;
@@ -313,30 +358,131 @@ static void r300_emit_draw_elements(struct r300_context *r300,
OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) |
(0 << R300_INDX_BUFFER_SKIP_SHIFT));
OUT_CS(offset_dwords << 2);
- OUT_CS_RELOC(indexBuffer, count_dwords,
- RADEON_GEM_DOMAIN_GTT, 0, 0);
+ OUT_CS_BUF_RELOC(indexBuffer, count_dwords,
+ RADEON_GEM_DOMAIN_GTT, 0, 0);
+
+ END_CS;
+}
+
+/*****************************************************************************
+ * The emission of draw packets for r300 which take care of the two-sided *
+ * stencil ref fallback and call r500's functions. *
+ ****************************************************************************/
+
+/* Set drawing for front faces. */
+static void r300_begin_stencil_ref_fallback(struct r300_context *r300)
+{
+ struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(2);
+ OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode | R300_CULL_BACK);
+ END_CS;
+}
+
+/* Set drawing for back faces. */
+static void r300_switch_stencil_ref_side(struct r300_context *r300)
+{
+ struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(4);
+ OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode | R300_CULL_FRONT);
+ OUT_CS_REG(R300_ZB_STENCILREFMASK,
+ dsa->stencil_ref_bf | r300->stencil_ref.ref_value[1]);
+ END_CS;
+}
+
+/* Restore the original state. */
+static void r300_end_stencil_ref_fallback(struct r300_context *r300)
+{
+ struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+ CS_LOCALS(r300);
+ BEGIN_CS(4);
+ OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode);
+ OUT_CS_REG(R300_ZB_STENCILREFMASK,
+ dsa->stencil_ref_mask | r300->stencil_ref.ref_value[0]);
END_CS;
}
+void r300_emit_draw_arrays_immediate(struct r300_context *r300,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
+{
+ if (!r300->stencil_ref_bf_fallback) {
+ r500_emit_draw_arrays_immediate(r300, mode, start, count);
+ } else {
+ r300_begin_stencil_ref_fallback(r300);
+ r500_emit_draw_arrays_immediate(r300, mode, start, count);
+ r300_switch_stencil_ref_side(r300);
+ r500_emit_draw_arrays_immediate(r300, mode, start, count);
+ r300_end_stencil_ref_fallback(r300);
+ }
+}
+
+void r300_emit_draw_arrays(struct r300_context *r300,
+ unsigned mode,
+ unsigned count)
+{
+ if (!r300->stencil_ref_bf_fallback) {
+ r500_emit_draw_arrays(r300, mode, count);
+ } else {
+ r300_begin_stencil_ref_fallback(r300);
+ r500_emit_draw_arrays(r300, mode, count);
+ r300_switch_stencil_ref_side(r300);
+ r500_emit_draw_arrays(r300, mode, count);
+ r300_end_stencil_ref_fallback(r300);
+ }
+}
+
+void r300_emit_draw_elements(struct r300_context *r300,
+ struct pipe_resource* indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
+{
+ if (!r300->stencil_ref_bf_fallback) {
+ r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex,
+ maxIndex, mode, start, count);
+ } else {
+ r300_begin_stencil_ref_fallback(r300);
+ r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex,
+ maxIndex, mode, start, count);
+ r300_switch_stencil_ref_side(r300);
+ r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex,
+ maxIndex, mode, start, count);
+ r300_end_stencil_ref_fallback(r300);
+ }
+}
+
static void r300_shorten_ubyte_elts(struct r300_context* r300,
- struct pipe_buffer** elts,
+ struct pipe_resource** elts,
+ unsigned start,
unsigned count)
{
+ struct pipe_context* context = &r300->context;
struct pipe_screen* screen = r300->context.screen;
- struct pipe_buffer* new_elts;
+ struct pipe_resource* new_elts;
unsigned char *in_map;
unsigned short *out_map;
+ struct pipe_transfer *src_transfer, *dst_transfer;
unsigned i;
- new_elts = screen->buffer_create(screen, 32,
- PIPE_BUFFER_USAGE_INDEX |
- PIPE_BUFFER_USAGE_CPU_WRITE |
- PIPE_BUFFER_USAGE_GPU_READ,
- 2 * count);
+ new_elts = pipe_buffer_create(screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer);
+ out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer);
- in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ);
- out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE);
+ in_map += start;
for (i = 0; i < count; i++) {
*out_map = (unsigned short)*in_map;
@@ -344,15 +490,43 @@ static void r300_shorten_ubyte_elts(struct r300_context* r300,
out_map++;
}
- pipe_buffer_unmap(screen, *elts);
- pipe_buffer_unmap(screen, new_elts);
+ pipe_buffer_unmap(context, *elts, src_transfer);
+ pipe_buffer_unmap(context, new_elts, dst_transfer);
+
+ *elts = new_elts;
+}
+
+static void r300_align_ushort_elts(struct r300_context *r300,
+ struct pipe_resource **elts,
+ unsigned start, unsigned count)
+{
+ struct pipe_context* context = &r300->context;
+ struct pipe_transfer *in_transfer = NULL;
+ struct pipe_transfer *out_transfer = NULL;
+ struct pipe_resource* new_elts;
+ unsigned short *in_map;
+ unsigned short *out_map;
+
+ new_elts = pipe_buffer_create(context->screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts,
+ PIPE_TRANSFER_READ, &in_transfer);
+ out_map = pipe_buffer_map(context, new_elts,
+ PIPE_TRANSFER_WRITE, &out_transfer);
+
+ memcpy(out_map, in_map+start, 2 * count);
+
+ pipe_buffer_unmap(context, *elts, in_transfer);
+ pipe_buffer_unmap(context, new_elts, out_transfer);
*elts = new_elts;
}
/* This is the fast-path drawing & emission for HW TCL. */
void r300_draw_range_elements(struct pipe_context* pipe,
- struct pipe_buffer* indexBuffer,
+ struct pipe_resource* indexBuffer,
unsigned indexSize,
unsigned minIndex,
unsigned maxIndex,
@@ -361,40 +535,52 @@ void r300_draw_range_elements(struct pipe_context* pipe,
unsigned count)
{
struct r300_context* r300 = r300_context(pipe);
- struct pipe_buffer* orgIndexBuffer = indexBuffer;
+ struct pipe_resource* orgIndexBuffer = indexBuffer;
#if defined(ENABLE_ALT_NUM_VERTS)
- boolean alt_num_verts = r300_screen(pipe->screen)->caps->is_r500 &&
+ boolean alt_num_verts = r300->screen->caps.is_r500 &&
count > 65536;
#else
boolean alt_num_verts = FALSE;
#endif
unsigned short_count;
+ if (r300->skip_rendering) {
+ return;
+ }
+
if (!u_trim_pipe_prim(mode, &count)) {
return;
}
if (indexSize == 1) {
- r300_shorten_ubyte_elts(r300, &indexBuffer, count);
+ r300_shorten_ubyte_elts(r300, &indexBuffer, start, count);
indexSize = 2;
+ start = 0;
+ } else if (indexSize == 2 && start % 2 != 0) {
+ r300_align_ushort_elts(r300, &indexBuffer, start, count);
+ start = 0;
}
r300_update_derived_state(r300);
+ r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count);
+
/* 128 dwords for emit_aos and emit_draw_elements */
r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128);
r300_emit_buffer_validate(r300, TRUE, indexBuffer);
r300_emit_dirty_state(r300);
r300_emit_aos(r300, 0);
+ u_upload_flush(r300->upload_vb);
+ u_upload_flush(r300->upload_ib);
if (alt_num_verts || count <= 65535) {
- r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex,
- maxIndex, mode, start, count);
+ r300->emit_draw_elements(r300, indexBuffer, indexSize, minIndex,
+ maxIndex, mode, start, count);
} else {
do {
short_count = MIN2(count, 65534);
- r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex,
- maxIndex, mode, start, short_count);
+ r300->emit_draw_elements(r300, indexBuffer, indexSize, minIndex,
+ maxIndex, mode, start, short_count);
start += short_count;
count -= short_count;
@@ -409,13 +595,13 @@ void r300_draw_range_elements(struct pipe_context* pipe,
}
if (indexBuffer != orgIndexBuffer) {
- pipe->screen->buffer_destroy(indexBuffer);
+ pipe_resource_reference( &indexBuffer, NULL );
}
}
/* Simple helpers for context setup. Should probably be moved to util. */
void r300_draw_elements(struct pipe_context* pipe,
- struct pipe_buffer* indexBuffer,
+ struct pipe_resource* indexBuffer,
unsigned indexSize, unsigned mode,
unsigned start, unsigned count)
{
@@ -431,13 +617,17 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
{
struct r300_context* r300 = r300_context(pipe);
#if defined(ENABLE_ALT_NUM_VERTS)
- boolean alt_num_verts = r300_screen(pipe->screen)->caps->is_r500 &&
+ boolean alt_num_verts = r300->screen->caps.is_r500 &&
count > 65536;
#else
boolean alt_num_verts = FALSE;
#endif
unsigned short_count;
+ if (r300->skip_rendering) {
+ return;
+ }
+
if (!u_trim_pipe_prim(mode, &count)) {
return;
}
@@ -445,22 +635,22 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
r300_update_derived_state(r300);
if (immd_is_good_idea(r300, count)) {
- r300_emit_draw_arrays_immediate(r300, mode, start, count);
+ r300->emit_draw_arrays_immediate(r300, mode, start, count);
} else {
/* Make sure there are at least 128 spare dwords in the command buffer.
* (most of it being consumed by emit_aos) */
r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128);
- r300_emit_buffer_validate(r300, TRUE, 0);
+ r300_emit_buffer_validate(r300, TRUE, NULL);
r300_emit_dirty_state(r300);
if (alt_num_verts || count <= 65535) {
r300_emit_aos(r300, start);
- r300_emit_draw_arrays(r300, mode, count);
+ r300->emit_draw_arrays(r300, mode, count);
} else {
do {
short_count = MIN2(count, 65535);
r300_emit_aos(r300, start);
- r300_emit_draw_arrays(r300, mode, short_count);
+ r300->emit_draw_arrays(r300, mode, short_count);
start += short_count;
count -= short_count;
@@ -468,11 +658,12 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
/* Again, we emit both AOS and draw_arrays so there should be
* at least 128 spare dwords. */
if (count && r300_reserve_cs_space(r300, 128)) {
- r300_emit_buffer_validate(r300, TRUE, 0);
+ r300_emit_buffer_validate(r300, TRUE, NULL);
r300_emit_dirty_state(r300);
}
} while (count);
}
+ u_upload_flush(r300->upload_vb);
}
}
@@ -488,39 +679,39 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe,
unsigned count)
{
struct r300_context* r300 = r300_context(pipe);
+ struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
int i;
+ if (r300->skip_rendering) {
+ return;
+ }
+
if (!u_trim_pipe_prim(mode, &count)) {
return;
}
for (i = 0; i < r300->vertex_buffer_count; i++) {
- void* buf = pipe_buffer_map(pipe->screen,
+ void* buf = pipe_buffer_map(pipe,
r300->vertex_buffer[i].buffer,
- PIPE_BUFFER_USAGE_CPU_READ);
+ PIPE_TRANSFER_READ,
+ &vb_transfer[i]);
draw_set_mapped_vertex_buffer(r300->draw, i, buf);
}
draw_set_mapped_element_buffer(r300->draw, 0, NULL);
- draw_set_mapped_constant_buffer(r300->draw,
- PIPE_SHADER_VERTEX,
- 0,
- r300->shader_constants[PIPE_SHADER_VERTEX].constants,
- r300->shader_constants[PIPE_SHADER_VERTEX].count *
- (sizeof(float) * 4));
-
draw_arrays(r300->draw, mode, start, count);
for (i = 0; i < r300->vertex_buffer_count; i++) {
- pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer);
+ pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
+ vb_transfer[i]);
draw_set_mapped_vertex_buffer(r300->draw, i, NULL);
}
}
/* SW TCL elements, using Draw. */
void r300_swtcl_draw_range_elements(struct pipe_context* pipe,
- struct pipe_buffer* indexBuffer,
+ struct pipe_resource* indexBuffer,
unsigned indexSize,
unsigned minIndex,
unsigned maxIndex,
@@ -529,40 +720,42 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe,
unsigned count)
{
struct r300_context* r300 = r300_context(pipe);
+ struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
+ struct pipe_transfer *ib_transfer;
int i;
void* indices;
+ if (r300->skip_rendering) {
+ return;
+ }
+
if (!u_trim_pipe_prim(mode, &count)) {
return;
}
for (i = 0; i < r300->vertex_buffer_count; i++) {
- void* buf = pipe_buffer_map(pipe->screen,
+ void* buf = pipe_buffer_map(pipe,
r300->vertex_buffer[i].buffer,
- PIPE_BUFFER_USAGE_CPU_READ);
+ PIPE_TRANSFER_READ,
+ &vb_transfer[i]);
draw_set_mapped_vertex_buffer(r300->draw, i, buf);
}
- indices = pipe_buffer_map(pipe->screen, indexBuffer,
- PIPE_BUFFER_USAGE_CPU_READ);
+ indices = pipe_buffer_map(pipe, indexBuffer,
+ PIPE_TRANSFER_READ, &ib_transfer);
draw_set_mapped_element_buffer_range(r300->draw, indexSize,
minIndex, maxIndex, indices);
- draw_set_mapped_constant_buffer(r300->draw,
- PIPE_SHADER_VERTEX,
- 0,
- r300->shader_constants[PIPE_SHADER_VERTEX].constants,
- r300->shader_constants[PIPE_SHADER_VERTEX].count *
- (sizeof(float) * 4));
-
draw_arrays(r300->draw, mode, start, count);
for (i = 0; i < r300->vertex_buffer_count; i++) {
- pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer);
+ pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
+ vb_transfer[i]);
draw_set_mapped_vertex_buffer(r300->draw, i, NULL);
}
- pipe_buffer_unmap(pipe->screen, indexBuffer);
+ pipe_buffer_unmap(pipe, indexBuffer,
+ ib_transfer);
draw_set_mapped_element_buffer_range(r300->draw, 0, start,
start + count - 1, NULL);
}
@@ -581,11 +774,13 @@ struct r300_render {
unsigned hwprim;
/* VBO */
- struct pipe_buffer* vbo;
+ struct pipe_resource* vbo;
size_t vbo_size;
size_t vbo_offset;
size_t vbo_max_used;
void * vbo_ptr;
+
+ struct pipe_transfer *vbo_transfer;
};
static INLINE struct r300_render*
@@ -616,13 +811,12 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render,
if (size + r300render->vbo_offset > r300render->vbo_size)
{
- pipe_buffer_reference(&r300->vbo, NULL);
+ pipe_resource_reference(&r300->vbo, NULL);
r300render->vbo = pipe_buffer_create(screen,
- 64,
- PIPE_BUFFER_USAGE_VERTEX,
- R300_MAX_VBO_SIZE);
+ PIPE_BIND_VERTEX_BUFFER,
+ R300_MAX_DRAW_VBO_SIZE);
r300render->vbo_offset = 0;
- r300render->vbo_size = R300_MAX_VBO_SIZE;
+ r300render->vbo_size = R300_MAX_DRAW_VBO_SIZE;
}
r300render->vertex_size = vertex_size;
@@ -635,10 +829,11 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render,
static void* r300_render_map_vertices(struct vbuf_render* render)
{
struct r300_render* r300render = r300_render(render);
- struct pipe_screen* screen = r300render->r300->context.screen;
- r300render->vbo_ptr = pipe_buffer_map(screen, r300render->vbo,
- PIPE_BUFFER_USAGE_CPU_WRITE);
+ r300render->vbo_ptr = pipe_buffer_map(&r300render->r300->context,
+ r300render->vbo,
+ PIPE_TRANSFER_WRITE,
+ &r300render->vbo_transfer);
return ((uint8_t*)r300render->vbo_ptr + r300render->vbo_offset);
}
@@ -648,7 +843,7 @@ static void r300_render_unmap_vertices(struct vbuf_render* render,
ushort max)
{
struct r300_render* r300render = r300_render(render);
- struct pipe_screen* screen = r300render->r300->context.screen;
+ struct pipe_context* context = &r300render->r300->context;
CS_LOCALS(r300render->r300);
BEGIN_CS(2);
OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max);
@@ -656,7 +851,7 @@ static void r300_render_unmap_vertices(struct vbuf_render* render,
r300render->vbo_max_used = MAX2(r300render->vbo_max_used,
r300render->vertex_size * (max + 1));
- pipe_buffer_unmap(screen, r300render->vbo);
+ pipe_buffer_unmap(context, r300render->vbo, r300render->vbo_transfer);
}
static void r300_render_release_vertices(struct vbuf_render* render)
@@ -678,9 +873,9 @@ static boolean r300_render_set_primitive(struct vbuf_render* render,
return TRUE;
}
-static void r300_render_draw_arrays(struct vbuf_render* render,
- unsigned start,
- unsigned count)
+static void r500_render_draw_arrays(struct vbuf_render* render,
+ unsigned start,
+ unsigned count)
{
struct r300_render* r300render = r300_render(render);
struct r300_context* r300 = r300render->r300;
@@ -688,6 +883,7 @@ static void r300_render_draw_arrays(struct vbuf_render* render,
CS_LOCALS(r300);
r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2);
+ r300_emit_buffer_validate(r300, FALSE, NULL);
r300_emit_dirty_state(r300);
DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count);
@@ -699,9 +895,9 @@ static void r300_render_draw_arrays(struct vbuf_render* render,
END_CS;
}
-static void r300_render_draw(struct vbuf_render* render,
- const ushort* indices,
- uint count)
+static void r500_render_draw(struct vbuf_render* render,
+ const ushort* indices,
+ uint count)
{
struct r300_render* r300render = r300_render(render);
struct r300_context* r300 = r300render->r300;
@@ -711,6 +907,7 @@ static void r300_render_draw(struct vbuf_render* render,
CS_LOCALS(r300);
r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords);
+ r300_emit_buffer_validate(r300, FALSE, NULL);
r300_emit_dirty_state(r300);
BEGIN_CS(dwords);
@@ -726,6 +923,40 @@ static void r300_render_draw(struct vbuf_render* render,
END_CS;
}
+static void r300_render_draw_arrays(struct vbuf_render* render,
+ unsigned start,
+ unsigned count)
+{
+ struct r300_context* r300 = r300_render(render)->r300;
+
+ if (!r300->stencil_ref_bf_fallback) {
+ r500_render_draw_arrays(render, start, count);
+ } else {
+ r300_begin_stencil_ref_fallback(r300);
+ r500_render_draw_arrays(render, start, count);
+ r300_switch_stencil_ref_side(r300);
+ r500_render_draw_arrays(render, start, count);
+ r300_end_stencil_ref_fallback(r300);
+ }
+}
+
+static void r300_render_draw(struct vbuf_render* render,
+ const ushort* indices,
+ uint count)
+{
+ struct r300_context* r300 = r300_render(render)->r300;
+
+ if (!r300->stencil_ref_bf_fallback) {
+ r500_render_draw(render, indices, count);
+ } else {
+ r300_begin_stencil_ref_fallback(r300);
+ r500_render_draw(render, indices, count);
+ r300_switch_stencil_ref_side(r300);
+ r500_render_draw(render, indices, count);
+ r300_end_stencil_ref_fallback(r300);
+ }
+}
+
static void r300_render_destroy(struct vbuf_render* render)
{
FREE(render);
@@ -746,8 +977,13 @@ static struct vbuf_render* r300_render_create(struct r300_context* r300)
r300render->base.map_vertices = r300_render_map_vertices;
r300render->base.unmap_vertices = r300_render_unmap_vertices;
r300render->base.set_primitive = r300_render_set_primitive;
- r300render->base.draw = r300_render_draw;
- r300render->base.draw_arrays = r300_render_draw_arrays;
+ if (r300->screen->caps.is_r500) {
+ r300render->base.draw = r500_render_draw;
+ r300render->base.draw_arrays = r500_render_draw_arrays;
+ } else {
+ r300render->base.draw = r300_render_draw;
+ r300render->base.draw_arrays = r300_render_draw_arrays;
+ }
r300render->base.release_vertices = r300_render_release_vertices;
r300render->base.destroy = r300_render_destroy;
diff --git a/src/gallium/drivers/r300/r300_render.h b/src/gallium/drivers/r300/r300_render.h
index 27b5e6a963..85da6135f5 100644
--- a/src/gallium/drivers/r300/r300_render.h
+++ b/src/gallium/drivers/r300/r300_render.h
@@ -23,10 +23,44 @@
#ifndef R300_RENDER_H
#define R300_RENDER_H
-uint32_t r300_translate_primitive(unsigned prim);
+void r500_emit_draw_arrays_immediate(struct r300_context *r300,
+ unsigned mode,
+ unsigned start,
+ unsigned count);
+
+void r500_emit_draw_arrays(struct r300_context *r300,
+ unsigned mode,
+ unsigned count);
+
+void r500_emit_draw_elements(struct r300_context *r300,
+ struct pipe_resource* indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count);
+
+void r300_emit_draw_arrays_immediate(struct r300_context *r300,
+ unsigned mode,
+ unsigned start,
+ unsigned count);
+
+void r300_emit_draw_arrays(struct r300_context *r300,
+ unsigned mode,
+ unsigned count);
+
+void r300_emit_draw_elements(struct r300_context *r300,
+ struct pipe_resource* indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count);
void r300_draw_range_elements(struct pipe_context* pipe,
- struct pipe_buffer* indexBuffer,
+ struct pipe_resource* indexBuffer,
unsigned indexSize,
unsigned minIndex,
unsigned maxIndex,
@@ -35,7 +69,7 @@ void r300_draw_range_elements(struct pipe_context* pipe,
unsigned count);
void r300_draw_elements(struct pipe_context* pipe,
- struct pipe_buffer* indexBuffer,
+ struct pipe_resource* indexBuffer,
unsigned indexSize, unsigned mode,
unsigned start, unsigned count);
@@ -48,7 +82,7 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe,
unsigned count);
void r300_swtcl_draw_range_elements(struct pipe_context* pipe,
- struct pipe_buffer* indexBuffer,
+ struct pipe_resource* indexBuffer,
unsigned indexSize,
unsigned minIndex,
unsigned maxIndex,
diff --git a/src/gallium/drivers/r300/r300_resource.c b/src/gallium/drivers/r300/r300_resource.c
new file mode 100644
index 0000000000..7ed47eaa60
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_resource.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2010 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ */
+
+#include <stdio.h>
+
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "util/u_memory.h"
+#include "util/u_upload_mgr.h"
+#include "util/u_math.h"
+
+#include "r300_context.h"
+#include "r300_texture.h"
+#include "r300_screen.h"
+#include "r300_screen_buffer.h"
+#include "r300_winsys.h"
+
+static struct pipe_resource *
+r300_resource_create(struct pipe_screen *screen,
+ const struct pipe_resource *templ)
+{
+ if (templ->target == PIPE_BUFFER)
+ return r300_buffer_create(screen, templ);
+ else
+ return r300_texture_create(screen, templ);
+
+}
+
+static struct pipe_resource *
+r300_resource_from_handle(struct pipe_screen * screen,
+ const struct pipe_resource *templ,
+ struct winsys_handle *whandle)
+{
+ if (templ->target == PIPE_BUFFER)
+ return NULL;
+ else
+ return r300_texture_from_handle(screen, templ, whandle);
+}
+
+void r300_init_resource_functions(struct r300_context *r300)
+{
+ r300->context.get_transfer = u_get_transfer_vtbl;
+ r300->context.transfer_map = u_transfer_map_vtbl;
+ r300->context.transfer_flush_region = u_transfer_flush_region_vtbl;
+ r300->context.transfer_unmap = u_transfer_unmap_vtbl;
+ r300->context.transfer_destroy = u_transfer_destroy_vtbl;
+ r300->context.transfer_inline_write = u_transfer_inline_write_vtbl;
+ r300->context.is_resource_referenced = u_is_resource_referenced_vtbl;
+}
+
+void r300_init_screen_resource_functions(struct r300_screen *r300screen)
+{
+ r300screen->screen.resource_create = r300_resource_create;
+ r300screen->screen.resource_from_handle = r300_resource_from_handle;
+ r300screen->screen.resource_get_handle = u_resource_get_handle_vtbl;
+ r300screen->screen.resource_destroy = u_resource_destroy_vtbl;
+ r300screen->screen.user_buffer_create = r300_user_buffer_create;
+
+ r300screen->screen.get_tex_surface = r300_get_tex_surface;
+ r300screen->screen.tex_surface_destroy = r300_tex_surface_destroy;
+}
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index d397a8eb2b..8fc1d5aa00 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -1,5 +1,6 @@
/*
* Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Copyright 2010 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"),
@@ -20,16 +21,12 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
-#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_memory.h"
-#include "util/u_simple_screen.h"
#include "r300_context.h"
-#include "r300_screen.h"
#include "r300_texture.h"
-
-#include "radeon_winsys.h"
+#include "r300_screen_buffer.h"
#include "r300_winsys.h"
/* Return the identifier behind whom the brave coders responsible for this
@@ -75,7 +72,7 @@ static const char* r300_get_name(struct pipe_screen* pscreen)
{
struct r300_screen* r300screen = r300_screen(pscreen);
- return chip_families[r300screen->caps->family];
+ return chip_families[r300screen->caps.family];
}
static int r300_get_param(struct pipe_screen* pscreen, int param)
@@ -85,18 +82,13 @@ static int r300_get_param(struct pipe_screen* pscreen, int param)
switch (param) {
case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
case PIPE_CAP_MAX_COMBINED_SAMPLERS:
- /* XXX I'm told this goes up to 16 */
- return 8;
+ return r300screen->caps.num_tex_units;
case PIPE_CAP_NPOT_TEXTURES:
/* XXX enable now to get GL2.1 API,
* figure out later how to emulate this */
return 1;
case PIPE_CAP_TWO_SIDED_STENCIL:
- if (r300screen->caps->is_r500) {
- return 1;
- } else {
- return 0;
- }
+ return 1;
case PIPE_CAP_GLSL:
/* I'll be frank. This is a lie.
*
@@ -129,7 +121,7 @@ static int r300_get_param(struct pipe_screen* pscreen, int param)
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
- if (r300screen->caps->is_r500) {
+ if (r300screen->caps.is_r500) {
/* 13 == 4096 */
return 13;
} else {
@@ -147,7 +139,7 @@ static int r300_get_param(struct pipe_screen* pscreen, int param)
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
return 1;
case PIPE_CAP_SM3:
- if (r300screen->caps->is_r500) {
+ if (r300screen->caps.is_r500) {
return 1;
} else {
return 0;
@@ -167,7 +159,7 @@ static int r300_get_param(struct pipe_screen* pscreen, int param)
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
return 0;
default:
- debug_printf("r300: Implementation error: Bad param %d\n",
+ fprintf(stderr, "r300: Implementation error: Bad param %d\n",
param);
return 0;
}
@@ -184,9 +176,9 @@ static float r300_get_paramf(struct pipe_screen* pscreen, int param)
case PIPE_CAP_MAX_POINT_WIDTH_AA:
/* The maximum dimensions of the colorbuffer are our practical
* rendering limits. 2048 pixels should be enough for anybody. */
- if (r300screen->caps->is_r500) {
+ if (r300screen->caps.is_r500) {
return 4096.0f;
- } else if (r300screen->caps->is_r400) {
+ } else if (r300screen->caps.is_r400) {
return 4021.0f;
} else {
return 2560.0f;
@@ -196,7 +188,7 @@ static float r300_get_paramf(struct pipe_screen* pscreen, int param)
case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
return 16.0f;
default:
- debug_printf("r300: Implementation error: Bad paramf %d\n",
+ fprintf(stderr, "r300: Implementation error: Bad paramf %d\n",
param);
return 0.0f;
}
@@ -209,140 +201,110 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
unsigned geom_flags)
{
uint32_t retval = 0;
- boolean is_r500 = r300_screen(screen)->caps->is_r500;
+ boolean is_r500 = r300_screen(screen)->caps.is_r500;
+ boolean is_r400 = r300_screen(screen)->caps.is_r400;
boolean is_z24 = format == PIPE_FORMAT_X8Z24_UNORM ||
- format == PIPE_FORMAT_S8Z24_UNORM;
- boolean is_color2101010 = format == PIPE_FORMAT_R10G10B10A2_UNORM;
+ format == PIPE_FORMAT_S8_USCALED_Z24_UNORM;
+ boolean is_color2101010 = format == PIPE_FORMAT_R10G10B10A2_UNORM ||
+ format == PIPE_FORMAT_R10G10B10X2_SNORM ||
+ format == PIPE_FORMAT_B10G10R10A2_UNORM ||
+ format == PIPE_FORMAT_R10SG10SB10SA2U_NORM;
+ boolean is_ati1n = format == PIPE_FORMAT_RGTC1_UNORM ||
+ format == PIPE_FORMAT_RGTC1_SNORM;
+ boolean is_ati2n = format == PIPE_FORMAT_RGTC2_UNORM ||
+ format == PIPE_FORMAT_RGTC2_SNORM;
if (target >= PIPE_MAX_TEXTURE_TYPES) {
- debug_printf("r300: Implementation error: Received bogus texture "
+ fprintf(stderr, "r300: Implementation error: Received bogus texture "
"target %d in %s\n", target, __FUNCTION__);
return FALSE;
}
/* Check sampler format support. */
- if ((usage & PIPE_TEXTURE_USAGE_SAMPLER) &&
+ if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
/* Z24 cannot be sampled from on non-r5xx. */
(is_r500 || !is_z24) &&
+ /* ATI1N is r5xx-only. */
+ (is_r500 || !is_ati1n) &&
+ /* ATI2N is supported on r4xx-r5xx. */
+ (is_r400 || is_r500 || !is_ati2n) &&
r300_is_sampler_format_supported(format)) {
- retval |= PIPE_TEXTURE_USAGE_SAMPLER;
+ retval |= PIPE_BIND_SAMPLER_VIEW;
}
/* Check colorbuffer format support. */
- if ((usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET |
- PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
- PIPE_TEXTURE_USAGE_PRIMARY)) &&
+ if ((usage & (PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SCANOUT |
+ PIPE_BIND_SHARED)) &&
/* 2101010 cannot be rendered to on non-r5xx. */
(is_r500 || !is_color2101010) &&
r300_is_colorbuffer_format_supported(format)) {
retval |= usage &
- (PIPE_TEXTURE_USAGE_RENDER_TARGET |
- PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
- PIPE_TEXTURE_USAGE_PRIMARY);
+ (PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SCANOUT |
+ PIPE_BIND_SHARED);
}
/* Check depth-stencil format support. */
- if (usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL &&
+ if (usage & PIPE_BIND_DEPTH_STENCIL &&
r300_is_zs_format_supported(format)) {
- retval |= PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ retval |= PIPE_BIND_DEPTH_STENCIL;
}
return retval == usage;
}
-static struct pipe_transfer*
-r300_get_tex_transfer(struct pipe_screen *screen,
- struct pipe_texture *texture,
- unsigned face, unsigned level, unsigned zslice,
- enum pipe_transfer_usage usage, unsigned x, unsigned y,
- unsigned w, unsigned h)
+static void r300_destroy_screen(struct pipe_screen* pscreen)
{
- struct r300_texture *tex = (struct r300_texture *)texture;
- struct r300_transfer *trans;
- struct r300_screen *rscreen = r300_screen(screen);
- unsigned offset;
-
- offset = r300_texture_get_offset(tex, level, zslice, face); /* in bytes */
+ struct r300_screen* r300screen = r300_screen(pscreen);
+ struct r300_winsys_screen *rws = r300_winsys_screen(pscreen);
- trans = CALLOC_STRUCT(r300_transfer);
- if (trans) {
- pipe_texture_reference(&trans->transfer.texture, texture);
- trans->transfer.x = x;
- trans->transfer.y = y;
- trans->transfer.width = w;
- trans->transfer.height = h;
- trans->transfer.stride = r300_texture_get_stride(rscreen, tex, level);
- trans->transfer.usage = usage;
- trans->transfer.zslice = zslice;
- trans->transfer.face = face;
+ if (rws)
+ rws->destroy(rws);
- trans->offset = offset;
- }
- return &trans->transfer;
+ FREE(r300screen);
}
-static void
-r300_tex_transfer_destroy(struct pipe_transfer *trans)
+static void r300_fence_reference(struct pipe_screen *screen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
{
- pipe_texture_reference(&trans->texture, NULL);
- FREE(trans);
}
-static void* r300_transfer_map(struct pipe_screen* screen,
- struct pipe_transfer* transfer)
+static int r300_fence_signalled(struct pipe_screen *screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags)
{
- struct r300_texture* tex = (struct r300_texture*)transfer->texture;
- char* map;
- enum pipe_format format = tex->tex.format;
-
- map = pipe_buffer_map(screen, tex->buffer,
- pipe_transfer_buffer_flags(transfer));
-
- if (!map) {
- return NULL;
- }
-
- return map + r300_transfer(transfer)->offset +
- transfer->y / util_format_get_blockheight(format) * transfer->stride +
- transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
+ return 0;
}
-static void r300_transfer_unmap(struct pipe_screen* screen,
- struct pipe_transfer* transfer)
+static int r300_fence_finish(struct pipe_screen *screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags)
{
- struct r300_texture* tex = (struct r300_texture*)transfer->texture;
- pipe_buffer_unmap(screen, tex->buffer);
+ return 0;
}
-static void r300_destroy_screen(struct pipe_screen* pscreen)
+struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws)
{
- struct r300_screen* r300screen = r300_screen(pscreen);
-
- FREE(r300screen->caps);
- FREE(r300screen);
-}
+ struct r300_screen *r300screen = CALLOC_STRUCT(r300_screen);
-struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys)
-{
- struct r300_screen* r300screen = CALLOC_STRUCT(r300_screen);
- struct r300_capabilities* caps = CALLOC_STRUCT(r300_capabilities);
-
- if (!r300screen || !caps) {
+ if (!r300screen) {
FREE(r300screen);
- FREE(caps);
return NULL;
}
- caps->pci_id = radeon_winsys->pci_id;
- caps->num_frag_pipes = radeon_winsys->gb_pipes;
- caps->num_z_pipes = radeon_winsys->z_pipes;
+ r300screen->caps.pci_id = rws->get_value(rws, R300_VID_PCI_ID);
+ r300screen->caps.num_frag_pipes = rws->get_value(rws, R300_VID_GB_PIPES);
+ r300screen->caps.num_z_pipes = rws->get_value(rws, R300_VID_Z_PIPES);
r300_init_debug(r300screen);
- r300_parse_chipset(caps);
+ r300_parse_chipset(&r300screen->caps);
- r300screen->caps = caps;
- r300screen->radeon_winsys = radeon_winsys;
- r300screen->screen.winsys = (struct pipe_winsys*)radeon_winsys;
+ r300screen->rws = rws;
+ r300screen->screen.winsys = (struct pipe_winsys*)rws;
r300screen->screen.destroy = r300_destroy_screen;
r300screen->screen.get_name = r300_get_name;
r300screen->screen.get_vendor = r300_get_vendor;
@@ -350,13 +312,18 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys)
r300screen->screen.get_paramf = r300_get_paramf;
r300screen->screen.is_format_supported = r300_is_format_supported;
r300screen->screen.context_create = r300_create_context;
- r300screen->screen.get_tex_transfer = r300_get_tex_transfer;
- r300screen->screen.tex_transfer_destroy = r300_tex_transfer_destroy;
- r300screen->screen.transfer_map = r300_transfer_map;
- r300screen->screen.transfer_unmap = r300_transfer_unmap;
- r300_init_screen_texture_functions(&r300screen->screen);
- u_simple_screen_init(&r300screen->screen);
+ r300screen->screen.fence_reference = r300_fence_reference;
+ r300screen->screen.fence_signalled = r300_fence_signalled;
+ r300screen->screen.fence_finish = r300_fence_finish;
+
+ r300_init_screen_resource_functions(r300screen);
return &r300screen->screen;
}
+
+struct r300_winsys_screen *
+r300_winsys_screen(struct pipe_screen *screen)
+{
+ return r300_screen(screen)->rws;
+}
diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h
index 502fbfa5a2..330bd9b36b 100644
--- a/src/gallium/drivers/r300/r300_screen.h
+++ b/src/gallium/drivers/r300/r300_screen.h
@@ -1,5 +1,6 @@
/*
* Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Copyright 2010 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"),
@@ -27,41 +28,27 @@
#include "r300_chipset.h"
-struct radeon_winsys;
+#include <stdio.h>
struct r300_screen {
/* Parent class */
struct pipe_screen screen;
- struct radeon_winsys* radeon_winsys;
+ struct r300_winsys_screen *rws;
/* Chipset capabilities */
- struct r300_capabilities* caps;
+ struct r300_capabilities caps;
/** Combination of DBG_xxx flags */
unsigned debug;
};
-struct r300_transfer {
- /* Parent class */
- struct pipe_transfer transfer;
-
- /* Offset from start of buffer. */
- unsigned offset;
-};
/* Convenience cast wrapper. */
static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) {
return (struct r300_screen*)screen;
}
-/* Convenience cast wrapper. */
-static INLINE struct r300_transfer*
-r300_transfer(struct pipe_transfer* transfer)
-{
- return (struct r300_transfer*)transfer;
-}
-
/* Debug functionality. */
/**
@@ -81,6 +68,9 @@ r300_transfer(struct pipe_transfer* transfer)
#define DBG_DRAW 0x0000010
#define DBG_TEX 0x0000020
#define DBG_FALL 0x0000040
+#define DBG_ANISOHQ 0x0000080
+#define DBG_NO_TILING 0x0000100
+#define DBG_NO_IMMD 0x0000200
/*@}*/
static INLINE boolean SCREEN_DBG_ON(struct r300_screen * screen, unsigned flags)
@@ -94,12 +84,13 @@ static INLINE void SCREEN_DBG(struct r300_screen * screen, unsigned flags,
if (SCREEN_DBG_ON(screen, flags)) {
va_list va;
va_start(va, fmt);
- debug_vprintf(fmt, va);
+ vfprintf(stderr, fmt, va);
va_end(va);
}
}
void r300_init_debug(struct r300_screen* ctx);
-#endif /* R300_SCREEN_H */
+void r300_init_screen_resource_functions(struct r300_screen *r300screen);
+#endif /* R300_SCREEN_H */
diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c
new file mode 100644
index 0000000000..20a9ffb9f6
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_screen_buffer.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2010 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ */
+
+#include <stdio.h>
+
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_upload_mgr.h"
+#include "util/u_math.h"
+
+#include "r300_screen_buffer.h"
+#include "r300_winsys.h"
+
+unsigned r300_buffer_is_referenced(struct pipe_context *context,
+ struct pipe_resource *buf,
+ enum r300_reference_domain domain)
+{
+ struct r300_context *r300 = r300_context(context);
+ struct r300_buffer *rbuf = r300_buffer(buf);
+
+ if (r300_buffer_is_user_buffer(buf))
+ return PIPE_UNREFERENCED;
+
+ if (r300->rws->is_buffer_referenced(r300->rws, rbuf->buf, domain))
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+
+ return PIPE_UNREFERENCED;
+}
+
+static unsigned r300_buffer_is_referenced_by_cs(struct pipe_context *context,
+ struct pipe_resource *buf,
+ unsigned face, unsigned level)
+{
+ return r300_buffer_is_referenced(context, buf, R300_REF_CS);
+}
+
+/* External helper, not required to implent u_resource_vtbl:
+ */
+int r300_upload_index_buffer(struct r300_context *r300,
+ struct pipe_resource **index_buffer,
+ unsigned index_size,
+ unsigned start,
+ unsigned count)
+{
+ struct pipe_resource *upload_buffer = NULL;
+ unsigned index_offset = start * index_size;
+ int ret = 0;
+
+ if (r300_buffer_is_user_buffer(*index_buffer)) {
+ ret = u_upload_buffer(r300->upload_ib,
+ index_offset,
+ count * index_size,
+ *index_buffer,
+ &index_offset,
+ &upload_buffer);
+ if (ret) {
+ goto done;
+ }
+ *index_buffer = upload_buffer;
+ }
+ done:
+ // if (upload_buffer)
+ // pipe_resource_reference(&upload_buffer, NULL);
+ return ret;
+}
+
+/* External helper, not required to implement u_resource_vtbl:
+ */
+int r300_upload_user_buffers(struct r300_context *r300)
+{
+ enum pipe_error ret = PIPE_OK;
+ int i, nr;
+
+ nr = r300->vertex_buffer_count;
+
+ for (i = 0; i < nr; i++) {
+ if (r300_buffer_is_user_buffer(r300->vertex_buffer[i].buffer)) {
+ struct pipe_resource *upload_buffer = NULL;
+ unsigned offset = 0; /*r300->vertex_buffer[i].buffer_offset * 4;*/
+ unsigned size = r300->vertex_buffer[i].buffer->width0;
+ unsigned upload_offset;
+ ret = u_upload_buffer(r300->upload_vb,
+ offset, size,
+ r300->vertex_buffer[i].buffer,
+ &upload_offset, &upload_buffer);
+ if (ret)
+ return ret;
+
+ pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL);
+ r300->vertex_buffer[i].buffer = upload_buffer;
+ r300->vertex_buffer[i].buffer_offset = upload_offset;
+ }
+ }
+ return ret;
+}
+
+static struct r300_winsys_buffer *
+r300_winsys_buffer_create(struct r300_screen *r300screen,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct r300_winsys_screen *rws = r300screen->rws;
+ struct r300_winsys_buffer *buf;
+
+ buf = rws->buffer_create(rws, alignment, usage, size);
+ return buf;
+}
+
+static void r300_winsys_buffer_destroy(struct r300_screen *r300screen,
+ struct r300_buffer *rbuf)
+{
+ struct r300_winsys_screen *rws = r300screen->rws;
+
+ if (rbuf->buf) {
+ rws->buffer_reference(rws, &rbuf->buf, NULL);
+ rbuf->buf = NULL;
+ }
+}
+
+static void r300_buffer_destroy(struct pipe_screen *screen,
+ struct pipe_resource *buf)
+{
+ struct r300_screen *r300screen = r300_screen(screen);
+ struct r300_buffer *rbuf = r300_buffer(buf);
+
+ r300_winsys_buffer_destroy(r300screen, rbuf);
+ FREE(rbuf);
+}
+
+static void *
+r300_buffer_transfer_map( struct pipe_context *pipe,
+ struct pipe_transfer *transfer )
+{
+ struct r300_screen *r300screen = r300_screen(pipe->screen);
+ struct r300_winsys_screen *rws = r300screen->rws;
+ struct r300_buffer *rbuf = r300_buffer(transfer->resource);
+ uint8_t *map;
+ boolean flush = FALSE;
+ unsigned i;
+
+ if (rbuf->user_buffer)
+ return (uint8_t *) rbuf->user_buffer + transfer->box.x;
+
+ if (rbuf->b.b.bind & PIPE_BIND_CONSTANT_BUFFER) {
+ goto just_map;
+ }
+
+ /* check if the mapping is to a range we already flushed */
+ if (transfer->usage & PIPE_TRANSFER_DISCARD) {
+ for (i = 0; i < rbuf->num_ranges; i++) {
+ if ((transfer->box.x >= rbuf->ranges[i].start) &&
+ (transfer->box.x < rbuf->ranges[i].end))
+ flush = TRUE;
+
+ if (flush) {
+ /* unreference this hw buffer and allocate a new one */
+ rws->buffer_reference(rws, &rbuf->buf, NULL);
+
+ rbuf->num_ranges = 0;
+ rbuf->buf = r300_winsys_buffer_create(r300screen,
+ 16,
+ rbuf->b.b.bind, /* XXX */
+ rbuf->b.b.width0);
+ break;
+ }
+ }
+ }
+just_map:
+ map = rws->buffer_map(rws, rbuf->buf, transfer->usage);
+
+ if (map == NULL)
+ return NULL;
+
+ /* map_buffer() returned a pointer to the beginning of the buffer,
+ * but transfers are expected to return a pointer to just the
+ * region specified in the box.
+ */
+ return map + transfer->box.x;
+}
+
+static void r300_buffer_transfer_flush_region( struct pipe_context *pipe,
+ struct pipe_transfer *transfer,
+ const struct pipe_box *box)
+{
+ struct r300_buffer *rbuf = r300_buffer(transfer->resource);
+ unsigned i;
+ unsigned offset = transfer->box.x + box->x;
+ unsigned length = box->width;
+
+ assert(box->x + box->width <= transfer->box.width);
+
+ if (rbuf->user_buffer)
+ return;
+
+ if (rbuf->b.b.bind & PIPE_BIND_CONSTANT_BUFFER)
+ return;
+
+ /* mark the range as used */
+ for(i = 0; i < rbuf->num_ranges; ++i) {
+ if(offset <= rbuf->ranges[i].end && rbuf->ranges[i].start <= (offset+box->width)) {
+ rbuf->ranges[i].start = MIN2(rbuf->ranges[i].start, offset);
+ rbuf->ranges[i].end = MAX2(rbuf->ranges[i].end, (offset+length));
+ return;
+ }
+ }
+
+ rbuf->ranges[rbuf->num_ranges].start = offset;
+ rbuf->ranges[rbuf->num_ranges].end = offset+length;
+ rbuf->num_ranges++;
+}
+
+static void r300_buffer_transfer_unmap( struct pipe_context *pipe,
+ struct pipe_transfer *transfer )
+{
+ struct r300_screen *r300screen = r300_screen(pipe->screen);
+ struct r300_winsys_screen *rws = r300screen->rws;
+ struct r300_buffer *rbuf = r300_buffer(transfer->resource);
+
+ if (rbuf->buf) {
+ rws->buffer_unmap(rws, rbuf->buf);
+ }
+}
+
+struct u_resource_vtbl r300_buffer_vtbl =
+{
+ u_default_resource_get_handle, /* get_handle */
+ r300_buffer_destroy, /* resource_destroy */
+ r300_buffer_is_referenced_by_cs, /* is_buffer_referenced */
+ u_default_get_transfer, /* get_transfer */
+ u_default_transfer_destroy, /* transfer_destroy */
+ r300_buffer_transfer_map, /* transfer_map */
+ r300_buffer_transfer_flush_region, /* transfer_flush_region */
+ r300_buffer_transfer_unmap, /* transfer_unmap */
+ u_default_transfer_inline_write /* transfer_inline_write */
+};
+
+struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
+ const struct pipe_resource *templ)
+{
+ struct r300_screen *r300screen = r300_screen(screen);
+ struct r300_buffer *rbuf;
+ unsigned alignment = 16;
+
+ rbuf = CALLOC_STRUCT(r300_buffer);
+ if (!rbuf)
+ goto error1;
+
+ rbuf->magic = R300_BUFFER_MAGIC;
+
+ rbuf->b.b = *templ;
+ rbuf->b.vtbl = &r300_buffer_vtbl;
+ pipe_reference_init(&rbuf->b.b.reference, 1);
+ rbuf->b.b.screen = screen;
+
+ if (rbuf->b.b.bind & R300_BIND_OQBO)
+ alignment = 4096;
+
+ rbuf->buf = r300_winsys_buffer_create(r300screen,
+ alignment,
+ rbuf->b.b.bind,
+ rbuf->b.b.width0);
+
+ if (!rbuf->buf)
+ goto error2;
+
+ return &rbuf->b.b;
+error2:
+ FREE(rbuf);
+error1:
+ return NULL;
+}
+
+struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen,
+ void *ptr,
+ unsigned bytes,
+ unsigned bind)
+{
+ struct r300_buffer *rbuf;
+
+ rbuf = CALLOC_STRUCT(r300_buffer);
+ if (!rbuf)
+ goto no_rbuf;
+
+ rbuf->magic = R300_BUFFER_MAGIC;
+
+ pipe_reference_init(&rbuf->b.b.reference, 1);
+ rbuf->b.vtbl = &r300_buffer_vtbl;
+ rbuf->b.b.screen = screen;
+ rbuf->b.b.format = PIPE_FORMAT_R8_UNORM;
+ rbuf->b.b._usage = PIPE_USAGE_IMMUTABLE;
+ rbuf->b.b.bind = bind;
+ rbuf->b.b.width0 = bytes;
+ rbuf->b.b.height0 = 1;
+ rbuf->b.b.depth0 = 1;
+
+ rbuf->user_buffer = ptr;
+ return &rbuf->b.b;
+
+no_rbuf:
+ return NULL;
+}
diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h
new file mode 100644
index 0000000000..57f48229b2
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_screen_buffer.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2010 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ */
+
+#ifndef R300_SCREEN_BUFFER_H
+#define R300_SCREEN_BUFFER_H
+
+#include <stdio.h>
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+#include "util/u_transfer.h"
+
+#include "r300_screen.h"
+#include "r300_winsys.h"
+#include "r300_context.h"
+
+#define R300_BUFFER_MAGIC 0xabcd1234
+#define R300_BUFFER_MAX_RANGES 32
+
+struct r300_buffer_range {
+ uint32_t start;
+ uint32_t end;
+};
+
+/* Vertex buffer. */
+struct r300_buffer
+{
+ struct u_resource b;
+
+ uint32_t magic;
+
+ struct r300_winsys_buffer *buf;
+
+ void *user_buffer;
+ struct r300_buffer_range ranges[R300_BUFFER_MAX_RANGES];
+ unsigned num_ranges;
+};
+
+/* Functions. */
+
+int r300_upload_user_buffers(struct r300_context *r300);
+
+int r300_upload_index_buffer(struct r300_context *r300,
+ struct pipe_resource **index_buffer,
+ unsigned index_size,
+ unsigned start,
+ unsigned count);
+
+struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
+ const struct pipe_resource *templ);
+
+struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen,
+ void *ptr,
+ unsigned bytes,
+ unsigned usage);
+
+unsigned r300_buffer_is_referenced(struct pipe_context *context,
+ struct pipe_resource *buf,
+ enum r300_reference_domain domain);
+
+/* Inline functions. */
+
+static INLINE struct r300_buffer *r300_buffer(struct pipe_resource *buffer)
+{
+ if (buffer) {
+ assert(((struct r300_buffer *)buffer)->magic == R300_BUFFER_MAGIC);
+ return (struct r300_buffer *)buffer;
+ }
+ return NULL;
+}
+
+static INLINE boolean r300_buffer_is_user_buffer(struct pipe_resource *buffer)
+{
+ return r300_buffer(buffer)->user_buffer ? true : false;
+}
+
+static INLINE boolean r300_add_buffer(struct r300_winsys_screen *rws,
+ struct pipe_resource *buffer,
+ int rd, int wr)
+{
+ struct r300_buffer *buf = r300_buffer(buffer);
+
+ if (!buf->buf)
+ return true;
+
+ return rws->add_buffer(rws, buf->buf, rd, wr);
+}
+
+static INLINE boolean r300_add_texture(struct r300_winsys_screen *rws,
+ struct r300_texture *tex,
+ int rd, int wr)
+{
+ return rws->add_buffer(rws, tex->buffer, rd, wr);
+}
+
+static INLINE void r300_buffer_write_reloc(struct r300_winsys_screen *rws,
+ struct r300_buffer *buf,
+ uint32_t rd, uint32_t wd, uint32_t flags)
+{
+ if (!buf->buf)
+ return;
+
+ rws->write_cs_reloc(rws, buf->buf, rd, wd, flags);
+}
+
+static INLINE void r300_texture_write_reloc(struct r300_winsys_screen *rws,
+ struct r300_texture *texture,
+ uint32_t rd, uint32_t wd, uint32_t flags)
+{
+ rws->write_cs_reloc(rws, texture->buffer, rd, wd, flags);
+}
+
+#endif
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index 9c5eba4206..9eb8539a65 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -32,13 +32,16 @@
#include "pipe/p_config.h"
#include "r300_context.h"
+#include "r300_emit.h"
#include "r300_reg.h"
#include "r300_screen.h"
+#include "r300_screen_buffer.h"
+#include "r300_state.h"
#include "r300_state_inlines.h"
#include "r300_fs.h"
+#include "r300_texture.h"
#include "r300_vs.h"
-
-#include "radeon_winsys.h"
+#include "r300_winsys.h"
/* r300_state: Functions used to intialize state context by translating
* Gallium state objects into semi-native r300 state objects. */
@@ -219,7 +222,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
/* Enable reading from the colorbuffer. */
blend->blend_control |= R300_READ_ENABLE;
- if (r300_screen(r300_context(pipe)->context.screen)->caps->is_r500) {
+ if (r300screen->caps.is_r500) {
/* Optimization: Depending on incoming pixels, we can
* conditionally disable the reading in hardware... */
if (eqRGB != PIPE_BLEND_MIN && eqA != PIPE_BLEND_MIN &&
@@ -308,7 +311,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
/* Color channel masks for all MRTs. */
blend->color_channel_mask = bgra_cmask(state->rt[0].colormask);
- if (r300screen->caps->is_r500 && state->independent_blend_enable) {
+ if (r300screen->caps.is_r500 && state->independent_blend_enable) {
if (state->rt[1].blend_enable) {
blend->color_channel_mask |= bgra_cmask(state->rt[1].colormask) << 4;
}
@@ -320,10 +323,17 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
}
}
+ /* Neither fglrx nor classic r300 ever set this, regardless of dithering
+ * state. Since it's an optional implementation detail, we can leave it
+ * out and never dither.
+ *
+ * This could be revisited if we ever get quality or conformance hints.
+ *
if (state->dither) {
blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT |
- R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT;
+ R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT;
}
+ */
return (void*)blend;
}
@@ -356,7 +366,6 @@ static void r300_set_blend_color(struct pipe_context* pipe,
const struct pipe_blend_color* color)
{
struct r300_context* r300 = r300_context(pipe);
- struct r300_screen* r300screen = r300_screen(pipe->screen);
struct r300_blend_color_state* state =
(struct r300_blend_color_state*)r300->blend_color_state.state;
union util_color uc;
@@ -372,7 +381,7 @@ static void r300_set_blend_color(struct pipe_context* pipe,
float_to_fixed10(color->color[2]) |
(float_to_fixed10(color->color[1]) << 16);
- r300->blend_color_state.size = r300screen->caps->is_r500 ? 3 : 2;
+ r300->blend_color_state.size = r300->screen->caps.is_r500 ? 3 : 2;
r300->blend_color_state.dirty = TRUE;
}
@@ -383,7 +392,7 @@ static void r300_set_clip_state(struct pipe_context* pipe,
r300->clip = *state;
- if (r300_screen(pipe->screen)->caps->has_tcl) {
+ if (r300->screen->caps.has_tcl) {
memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state));
r300->clip_state.size = 29;
} else {
@@ -404,8 +413,7 @@ static void*
r300_create_dsa_state(struct pipe_context* pipe,
const struct pipe_depth_stencil_alpha_state* state)
{
- struct r300_capabilities *caps =
- r300_screen(r300_context(pipe)->context.screen)->caps;
+ struct r300_capabilities *caps = &r300_screen(pipe->screen)->caps;
struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state);
/* Depth test setup. */
@@ -439,6 +447,8 @@ static void*
(state->stencil[0].writemask << R300_STENCILWRITEMASK_SHIFT);
if (state->stencil[1].enabled) {
+ dsa->two_sided = TRUE;
+
dsa->z_buffer_control |= R300_STENCIL_FRONT_BACK;
dsa->z_stencil_control |=
(r300_translate_depth_stencil_function(state->stencil[1].func) <<
@@ -450,14 +460,16 @@ static void*
(r300_translate_stencil_op(state->stencil[1].zfail_op) <<
R300_S_BACK_ZFAIL_OP_SHIFT);
- if (caps->is_r500)
- {
+ dsa->stencil_ref_bf =
+ (state->stencil[1].valuemask << R300_STENCILMASK_SHIFT) |
+ (state->stencil[1].writemask << R300_STENCILWRITEMASK_SHIFT);
+
+ if (caps->is_r500) {
dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK;
- dsa->stencil_ref_bf =
- (state->stencil[1].valuemask <<
- R300_STENCILMASK_SHIFT) |
- (state->stencil[1].writemask <<
- R300_STENCILWRITEMASK_SHIFT);
+ } else {
+ dsa->stencil_ref_bf_fallback =
+ (state->stencil[0].valuemask != state->stencil[1].valuemask ||
+ state->stencil[0].writemask != state->stencil[1].writemask);
}
}
}
@@ -478,13 +490,33 @@ static void*
return (void*)dsa;
}
+static void r300_update_stencil_ref_fallback_status(struct r300_context *r300)
+{
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+
+ if (r300->screen->caps.is_r500) {
+ return;
+ }
+
+ r300->stencil_ref_bf_fallback =
+ dsa->stencil_ref_bf_fallback ||
+ (dsa->two_sided &&
+ r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]);
+}
+
/* Bind DSA state. */
static void r300_bind_dsa_state(struct pipe_context* pipe,
void* state)
{
struct r300_context* r300 = r300_context(pipe);
+ if (!state) {
+ return;
+ }
+
UPDATE_STATE(state, r300->dsa_state);
+
+ r300_update_stencil_ref_fallback_status(r300);
}
/* Free DSA state. */
@@ -498,8 +530,11 @@ static void r300_set_stencil_ref(struct pipe_context* pipe,
const struct pipe_stencil_ref* sr)
{
struct r300_context* r300 = r300_context(pipe);
+
r300->stencil_ref = *sr;
r300->dsa_state.dirty = TRUE;
+
+ r300_update_stencil_ref_fallback_status(r300);
}
/* This switcheroo is needed just because of goddamned MACRO_SWITCH. */
@@ -522,46 +557,46 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
continue;
}
- tex = (struct r300_texture*)old_state->cbufs[i]->texture;
+ tex = r300_texture(old_state->cbufs[i]->texture);
if (tex) {
- r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer,
+ r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
tex->pitch[0],
- tex->microtile != 0,
- tex->macrotile != 0);
+ tex->microtile,
+ tex->macrotile);
}
}
if (old_state->zsbuf &&
(!new_state->zsbuf ||
old_state->zsbuf->texture != new_state->zsbuf->texture)) {
- tex = (struct r300_texture*)old_state->zsbuf->texture;
+ tex = r300_texture(old_state->zsbuf->texture);
if (tex) {
- r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer,
+ r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
tex->pitch[0],
- tex->microtile != 0,
- tex->macrotile != 0);
+ tex->microtile,
+ tex->macrotile);
}
}
/* Set tiling flags for new surfaces. */
for (i = 0; i < new_state->nr_cbufs; i++) {
- tex = (struct r300_texture*)new_state->cbufs[i]->texture;
+ tex = r300_texture(new_state->cbufs[i]->texture);
level = new_state->cbufs[i]->level;
- r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer,
+ r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
tex->pitch[level],
- tex->microtile != 0,
- tex->mip_macrotile[level] != 0);
+ tex->microtile,
+ tex->mip_macrotile[level]);
}
if (new_state->zsbuf) {
- tex = (struct r300_texture*)new_state->zsbuf->texture;
+ tex = r300_texture(new_state->zsbuf->texture);
level = new_state->zsbuf->level;
- r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer,
+ r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
tex->pitch[level],
- tex->microtile != 0,
- tex->mip_macrotile[level] != 0);
+ tex->microtile,
+ tex->mip_macrotile[level]);
}
}
@@ -570,48 +605,51 @@ static void
const struct pipe_framebuffer_state* state)
{
struct r300_context* r300 = r300_context(pipe);
- struct r300_screen* r300screen = r300_screen(pipe->screen);
+ struct pipe_framebuffer_state *old_state = r300->fb_state.state;
unsigned max_width, max_height;
uint32_t zbuffer_bpp = 0;
-
if (state->nr_cbufs > 4) {
- debug_printf("r300: Implementation error: Too many MRTs in %s, "
+ fprintf(stderr, "r300: Implementation error: Too many MRTs in %s, "
"refusing to bind framebuffer state!\n", __FUNCTION__);
return;
}
- if (r300screen->caps->is_r500) {
+ if (r300->screen->caps.is_r500) {
max_width = max_height = 4096;
- } else if (r300screen->caps->is_r400) {
+ } else if (r300->screen->caps.is_r400) {
max_width = max_height = 4021;
} else {
max_width = max_height = 2560;
}
if (state->width > max_width || state->height > max_height) {
- debug_printf("r300: Implementation error: Render targets are too "
+ fprintf(stderr, "r300: Implementation error: Render targets are too "
"big in %s, refusing to bind framebuffer state!\n", __FUNCTION__);
return;
}
-
if (r300->draw) {
draw_flush(r300->draw);
}
- memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state));
+ r300->fb_state.dirty = TRUE;
- r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) +
- (state->zsbuf ? 10 : 0) + 8;
+ /* If nr_cbufs is changed from zero to non-zero or vice versa... */
+ if (!!old_state->nr_cbufs != !!state->nr_cbufs) {
+ r300->blend_state.dirty = TRUE;
+ }
+ /* If zsbuf is set from NULL to non-NULL or vice versa.. */
+ if (!!old_state->zsbuf != !!state->zsbuf) {
+ r300->dsa_state.dirty = TRUE;
+ }
r300_fb_update_tiling_flags(r300, r300->fb_state.state, state);
- /* XXX wait what */
- r300->blend_state.dirty = TRUE;
- r300->dsa_state.dirty = TRUE;
- r300->fb_state.dirty = TRUE;
- r300->scissor_state.dirty = TRUE;
+ memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state));
+
+ r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) +
+ (state->zsbuf ? 10 : 0) + 11;
/* Polygon offset depends on the zbuffer bit depth. */
if (state->zsbuf && r300->polygon_offset_enabled) {
@@ -643,12 +681,28 @@ static void* r300_create_fs_state(struct pipe_context* pipe,
fs->state = *shader;
fs->state.tokens = tgsi_dup_tokens(shader->tokens);
- tgsi_scan_shader(shader->tokens, &fs->info);
- r300_shader_read_fs_inputs(&fs->info, &fs->inputs);
-
return (void*)fs;
}
+void r300_mark_fs_code_dirty(struct r300_context *r300)
+{
+ struct r300_fragment_shader* fs = r300_fs(r300);
+
+ r300->fs.dirty = TRUE;
+ r300->fs_rc_constant_state.dirty = TRUE;
+ r300->fs_constants.dirty = TRUE;
+
+ if (r300->screen->caps.is_r500) {
+ r300->fs.size = r500_get_fs_atom_size(r300);
+ r300->fs_rc_constant_state.size = fs->shader->rc_state_count * 7;
+ r300->fs_constants.size = fs->shader->externals_count * 4 + 3;
+ } else {
+ r300->fs.size = r300_get_fs_atom_size(r300);
+ r300->fs_rc_constant_state.size = fs->shader->rc_state_count * 5;
+ r300->fs_constants.size = fs->shader->externals_count * 4 + 1;
+ }
+}
+
/* Bind fragment shader state. */
static void r300_bind_fs_state(struct pipe_context* pipe, void* shader)
{
@@ -656,20 +710,19 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader)
struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader;
if (fs == NULL) {
- r300->fs = NULL;
+ r300->fs.state = NULL;
return;
}
- r300->fs = fs;
+ r300->fs.state = fs;
r300_pick_fragment_shader(r300);
+ r300_mark_fs_code_dirty(r300);
r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */
if (r300->vs_state.state && r300_vertex_shader_setup_wpos(r300)) {
r300->vap_output_state.dirty = TRUE;
}
-
- r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS;
}
/* Delete fragment shader state. */
@@ -704,8 +757,8 @@ static void r300_set_polygon_stipple(struct pipe_context* pipe,
static void* r300_create_rs_state(struct pipe_context* pipe,
const struct pipe_rasterizer_state* state)
{
- struct r300_screen* r300screen = r300_screen(pipe->screen);
struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state);
+ int i;
/* Copy rasterizer state for Draw. */
rs->rs = *state;
@@ -716,9 +769,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
rs->vap_control_status = R300_VC_32BIT_SWAP;
#endif
- /* If bypassing TCL, or if no TCL engine is present, turn off the HW TCL.
- * Else, enable HW TCL and force Draw's TCL off. */
- if (!r300screen->caps->has_tcl) {
+ /* If no TCL engine is present, turn off the HW TCL. */
+ if (!r300_screen(pipe->screen)->caps.has_tcl) {
rs->vap_control_status |= R300_VAP_TCL_BYPASS;
}
@@ -799,6 +851,32 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
rs->color_control = R300_SHADE_MODEL_SMOOTH;
}
+ rs->clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
+
+ /* Point sprites */
+ if (state->sprite_coord_enable) {
+ rs->stuffing_enable = R300_GB_POINT_STUFF_ENABLE;
+ for (i = 0; i < 8; i++) {
+ if (state->sprite_coord_enable & (1 << i))
+ rs->stuffing_enable |=
+ R300_GB_TEX_STR << (R300_GB_TEX0_SOURCE_SHIFT + (i*2));
+ }
+
+ rs->point_texcoord_left = 0.0f;
+ rs->point_texcoord_right = 1.0f;
+
+ switch (state->sprite_coord_mode) {
+ case PIPE_SPRITE_COORD_UPPER_LEFT:
+ rs->point_texcoord_top = 0.0f;
+ rs->point_texcoord_bottom = 1.0f;
+ break;
+ case PIPE_SPRITE_COORD_LOWER_LEFT:
+ rs->point_texcoord_top = 1.0f;
+ rs->point_texcoord_bottom = 0.0f;
+ break;
+ }
+ }
+
return (void*)rs;
}
@@ -807,6 +885,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
{
struct r300_context* r300 = r300_context(pipe);
struct r300_rs_state* rs = (struct r300_rs_state*)state;
+ int last_sprite_coord_enable = r300->sprite_coord_enable;
if (r300->draw) {
draw_flush(r300->draw);
@@ -815,20 +894,17 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
if (rs) {
r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw;
+ r300->sprite_coord_enable = rs->rs.sprite_coord_enable;
} else {
r300->polygon_offset_enabled = FALSE;
+ r300->sprite_coord_enable = 0;
}
UPDATE_STATE(state, r300->rs_state);
- r300->rs_state.size = 17 + (r300->polygon_offset_enabled ? 5 : 0);
-
- /* XXX Why is this still needed, dammit!? */
- r300->scissor_state.dirty = TRUE;
- r300->viewport_state.dirty = TRUE;
+ r300->rs_state.size = 26 + (r300->polygon_offset_enabled ? 5 : 0);
- /* XXX Clean these up when we move to atom emits */
- if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
- r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
+ if (last_sprite_coord_enable != r300->sprite_coord_enable) {
+ r300->rs_block_state.dirty = TRUE;
}
}
@@ -844,6 +920,7 @@ static void*
{
struct r300_context* r300 = r300_context(pipe);
struct r300_sampler_state* sampler = CALLOC_STRUCT(r300_sampler_state);
+ boolean is_r500 = r300->screen->caps.is_r500;
int lod_bias;
union util_color uc;
@@ -859,6 +936,8 @@ static void*
state->min_mip_filter,
state->max_anisotropy > 0);
+ sampler->filter0 |= r300_anisotropy(state->max_anisotropy);
+
/* Unfortunately, r300-r500 don't support floating-point mipmap lods. */
/* We must pass these to the merge function to clamp them properly. */
sampler->min_lod = MAX2((unsigned)state->min_lod, 0);
@@ -868,13 +947,19 @@ static void*
sampler->filter1 |= lod_bias << R300_LOD_BIAS_SHIFT;
- sampler->filter1 |= r300_anisotropy(state->max_anisotropy);
+ /* This is very high quality anisotropic filtering for R5xx.
+ * It's good for benchmarking the performance of texturing but
+ * in practice we don't want to slow down the driver because it's
+ * a pretty good performance killer. Feel free to play with it. */
+ if (DBG_ON(r300, DBG_ANISOHQ) && is_r500) {
+ sampler->filter1 |= r500_anisotropy(state->max_anisotropy);
+ }
util_pack_color(state->border_color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
sampler->border_color = uc.ui;
/* R500-specific fixups and optimizations */
- if (r300_screen(r300->context.screen)->caps->is_r500) {
+ if (r300->screen->caps.is_r500) {
sampler->filter1 |= R500_BORDER_FIX;
}
@@ -888,23 +973,16 @@ static void r300_bind_sampler_states(struct pipe_context* pipe,
struct r300_context* r300 = r300_context(pipe);
struct r300_textures_state* state =
(struct r300_textures_state*)r300->textures_state.state;
+ unsigned tex_units = r300->screen->caps.num_tex_units;
- if (count > 8) {
+ if (count > tex_units) {
return;
}
memcpy(state->sampler_states, states, sizeof(void*) * count);
- state->sampler_count = count;
+ state->sampler_state_count = count;
r300->textures_state.dirty = TRUE;
-
- /* Pick a fragment shader based on the texture compare state. */
- if (r300->fs && count) {
- if (r300_pick_fragment_shader(r300)) {
- r300->dirty_state |= R300_NEW_FRAGMENT_SHADER |
- R300_NEW_FRAGMENT_SHADER_CONSTANTS;
- }
- }
}
static void r300_lacks_vertex_textures(struct pipe_context* pipe,
@@ -918,45 +996,53 @@ static void r300_delete_sampler_state(struct pipe_context* pipe, void* state)
FREE(state);
}
-static void r300_set_sampler_textures(struct pipe_context* pipe,
- unsigned count,
- struct pipe_texture** texture)
+static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
+ unsigned count,
+ struct pipe_sampler_view** views)
{
struct r300_context* r300 = r300_context(pipe);
struct r300_textures_state* state =
(struct r300_textures_state*)r300->textures_state.state;
+ struct r300_texture *texture;
unsigned i;
- boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500;
+ unsigned tex_units = r300->screen->caps.num_tex_units;
boolean dirty_tex = FALSE;
- /* XXX magic num */
- if (count > 8) {
+ if (count > tex_units) {
return;
}
for (i = 0; i < count; i++) {
- if (state->textures[i] != (struct r300_texture*)texture[i]) {
- pipe_texture_reference((struct pipe_texture**)&state->textures[i],
- texture[i]);
+ if (&state->sampler_views[i]->base != views[i]) {
+ pipe_sampler_view_reference(
+ (struct pipe_sampler_view**)&state->sampler_views[i],
+ views[i]);
+
+ if (!views[i]) {
+ continue;
+ }
+
+ /* A new sampler view (= texture)... */
dirty_tex = TRUE;
- /* R300-specific - set the texrect factor in the fragment shader */
- if (!is_r500 && state->textures[i]->is_npot) {
- /* XXX It would be nice to re-emit just 1 constant,
- * XXX not all of them */
- r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
+ /* Set the texrect factor in the fragment shader.
+ * Needed for RECT and NPOT fallback. */
+ texture = r300_texture(views[i]->texture);
+ if (texture->uses_pitch) {
+ r300->fs_rc_constant_state.dirty = TRUE;
}
}
}
- for (i = count; i < 8; i++) {
- if (state->textures[i]) {
- pipe_texture_reference((struct pipe_texture**)&state->textures[i],
- NULL);
+ for (i = count; i < tex_units; i++) {
+ if (state->sampler_views[i]) {
+ pipe_sampler_view_reference(
+ (struct pipe_sampler_view**)&state->sampler_views[i],
+ NULL);
}
}
- state->texture_count = count;
+ state->sampler_view_count = count;
r300->textures_state.dirty = TRUE;
@@ -965,6 +1051,48 @@ static void r300_set_sampler_textures(struct pipe_context* pipe,
}
}
+static struct pipe_sampler_view *
+r300_create_sampler_view(struct pipe_context *pipe,
+ struct pipe_resource *texture,
+ const struct pipe_sampler_view *templ)
+{
+ struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view);
+ struct r300_texture *tex = r300_texture(texture);
+ unsigned char swizzle[4];
+
+ if (view) {
+ view->base = *templ;
+ view->base.reference.count = 1;
+ view->base.context = pipe;
+ view->base.texture = NULL;
+ pipe_resource_reference(&view->base.texture, texture);
+
+ swizzle[0] = templ->swizzle_r;
+ swizzle[1] = templ->swizzle_g;
+ swizzle[2] = templ->swizzle_b;
+ swizzle[3] = templ->swizzle_a;
+
+ /* XXX Enable swizzles when they become supported. Now we get RGBA
+ * everywhere. And do testing! */
+ view->format = tex->tx_format;
+ view->format.format1 |= r300_translate_texformat(templ->format,
+ 0); /*swizzle);*/
+ if (r300_screen(pipe->screen)->caps.is_r500) {
+ view->format.format2 |= r500_tx_format_msb_bit(templ->format);
+ }
+ }
+
+ return (struct pipe_sampler_view*)view;
+}
+
+static void
+r300_sampler_view_destroy(struct pipe_context *pipe,
+ struct pipe_sampler_view *view)
+{
+ pipe_resource_reference(&view->texture, NULL);
+ FREE(view);
+}
+
static void r300_set_scissor_state(struct pipe_context* pipe,
const struct pipe_scissor_state* state)
{
@@ -1014,8 +1142,8 @@ static void r300_set_viewport_state(struct pipe_context* pipe,
}
r300->viewport_state.dirty = TRUE;
- if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
- r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
+ if (r300->fs.state && r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) {
+ r300->fs_rc_constant_state.dirty = TRUE;
}
}
@@ -1024,63 +1152,177 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
const struct pipe_vertex_buffer* buffers)
{
struct r300_context* r300 = r300_context(pipe);
- unsigned i, max_index = ~0;
+ struct pipe_vertex_buffer *vbo;
+ unsigned i, max_index = (1 << 24) - 1;
+ boolean any_user_buffer = FALSE;
- memcpy(r300->vertex_buffer, buffers,
- sizeof(struct pipe_vertex_buffer) * count);
+ if (count == r300->vertex_buffer_count &&
+ memcmp(r300->vertex_buffer, buffers,
+ sizeof(struct pipe_vertex_buffer) * count) == 0) {
+ return;
+ }
+ /* Check if the stride is aligned to the size of DWORD. */
for (i = 0; i < count; i++) {
- max_index = MIN2(buffers[i].max_index, max_index);
+ if (buffers[i].buffer) {
+ if (buffers[i].stride % 4 != 0) {
+ // XXX Shouldn't we align the buffer?
+ fprintf(stderr, "r300: set_vertex_buffers: "
+ "Unaligned buffer stride %i isn't supported.\n",
+ buffers[i].stride);
+ abort();
+ }
+ }
}
+ for (i = 0; i < count; i++) {
+ /* Why, yes, I AM casting away constness. How did you know? */
+ vbo = (struct pipe_vertex_buffer*)&buffers[i];
+
+ /* Reference our buffer. */
+ pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer);
+
+ /* Skip NULL buffers */
+ if (!buffers[i].buffer) {
+ continue;
+ }
+
+ if (r300_buffer_is_user_buffer(vbo->buffer)) {
+ any_user_buffer = TRUE;
+ }
+
+ if (vbo->max_index == ~0) {
+ /* if no VBO stride then only one vertex value so max index is 1 */
+ /* should think about converting to VS constants like svga does */
+ if (!vbo->stride)
+ vbo->max_index = 1;
+ else
+ vbo->max_index =
+ (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride;
+ }
+
+ max_index = MIN2(vbo->max_index, max_index);
+ }
+
+ for (; i < r300->vertex_buffer_count; i++) {
+ /* Dereference any old buffers. */
+ pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL);
+ }
+
+ memcpy(r300->vertex_buffer, buffers,
+ sizeof(struct pipe_vertex_buffer) * count);
+
r300->vertex_buffer_count = count;
r300->vertex_buffer_max_index = max_index;
+ r300->any_user_vbs = any_user_buffer;
if (r300->draw) {
draw_flush(r300->draw);
draw_set_vertex_buffers(r300->draw, count, buffers);
- } else {
- r300->vertex_stream_state.dirty = TRUE;
}
}
-static boolean r300_validate_aos(struct r300_context *r300)
+/* Update the PSC tables. */
+static void r300_vertex_psc(struct r300_vertex_element_state *velems)
{
- struct pipe_vertex_buffer *vbuf = r300->vertex_buffer;
- struct pipe_vertex_element *velem = r300->vertex_element;
- int i;
+ struct r300_vertex_stream_state *vstream = &velems->vertex_stream;
+ uint16_t type, swizzle;
+ enum pipe_format format;
+ unsigned i;
- /* Check if formats and strides are aligned to the size of DWORD. */
- for (i = 0; i < r300->vertex_element_count; i++) {
- if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 ||
- util_format_get_blocksize(velem[i].src_format) % 4 != 0) {
- return FALSE;
+ if (velems->count > 16) {
+ fprintf(stderr, "r300: More than 16 vertex elements are not supported,"
+ " requested %i, using 16.\n", velems->count);
+ velems->count = 16;
+ }
+
+ /* Vertex shaders have no semantics on their inputs,
+ * so PSC should just route stuff based on the vertex elements,
+ * and not on attrib information. */
+ for (i = 0; i < velems->count; i++) {
+ format = velems->velem[i].src_format;
+
+ type = r300_translate_vertex_data_type(format) |
+ (i << R300_DST_VEC_LOC_SHIFT);
+ swizzle = r300_translate_vertex_data_swizzle(format);
+
+ if (i & 1) {
+ vstream->vap_prog_stream_cntl[i >> 1] |= type << 16;
+ vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16;
+ } else {
+ vstream->vap_prog_stream_cntl[i >> 1] |= type;
+ vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle;
}
}
- return TRUE;
+
+ /* Set the last vector in the PSC. */
+ if (i) {
+ i -= 1;
+ }
+ vstream->vap_prog_stream_cntl[i >> 1] |=
+ (R300_LAST_VEC << (i & 1 ? 16 : 0));
+
+ vstream->count = (i >> 1) + 1;
}
-static void r300_set_vertex_elements(struct pipe_context* pipe,
- unsigned count,
- const struct pipe_vertex_element* elements)
+static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
+ unsigned count,
+ const struct pipe_vertex_element* attribs)
{
- struct r300_context* r300 = r300_context(pipe);
+ struct r300_vertex_element_state *velems;
+ unsigned i, size;
+
+ assert(count <= PIPE_MAX_ATTRIBS);
+ velems = CALLOC_STRUCT(r300_vertex_element_state);
+ if (velems != NULL) {
+ velems->count = count;
+ memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count);
+
+ if (r300_screen(pipe->screen)->caps.has_tcl) {
+ /* Check if the format is aligned to the size of DWORD. */
+ for (i = 0; i < count; i++) {
+ size = util_format_get_blocksize(attribs[i].src_format);
+
+ if (size % 4 != 0) {
+ /* XXX Shouldn't we align the format? */
+ fprintf(stderr, "r300_create_vertex_elements_state: "
+ "Unaligned format %s:%i isn't supported\n",
+ util_format_name(attribs[i].src_format), size);
+ assert(0);
+ abort();
+ }
+ }
- memcpy(r300->vertex_element,
- elements,
- sizeof(struct pipe_vertex_element) * count);
- r300->vertex_element_count = count;
+ r300_vertex_psc(velems);
+ }
+ }
+ return velems;
+}
+
+static void r300_bind_vertex_elements_state(struct pipe_context *pipe,
+ void *state)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct r300_vertex_element_state *velems = state;
+
+ if (velems == NULL) {
+ return;
+ }
+
+ r300->velems = velems;
if (r300->draw) {
draw_flush(r300->draw);
- draw_set_vertex_elements(r300->draw, count, elements);
+ draw_set_vertex_elements(r300->draw, velems->count, velems->velem);
}
- if (!r300_validate_aos(r300)) {
- /* XXX We should fallback using draw. */
- assert(0);
- abort();
- }
+ UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state);
+ r300->vertex_stream_state.size = (1 + velems->vertex_stream.count) * 2;
+}
+
+static void r300_delete_vertex_elements_state(struct pipe_context *pipe, void *state)
+{
+ FREE(state);
}
static void* r300_create_vs_state(struct pipe_context* pipe,
@@ -1088,124 +1330,146 @@ static void* r300_create_vs_state(struct pipe_context* pipe,
{
struct r300_context* r300 = r300_context(pipe);
- if (r300_screen(pipe->screen)->caps->has_tcl) {
- struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader);
- /* Copy state directly into shader. */
- vs->state = *shader;
- vs->state.tokens = tgsi_dup_tokens(shader->tokens);
+ struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader);
- tgsi_scan_shader(shader->tokens, &vs->info);
+ /* Copy state directly into shader. */
+ vs->state = *shader;
+ vs->state.tokens = tgsi_dup_tokens(shader->tokens);
- return (void*)vs;
+ if (r300->screen->caps.has_tcl) {
+ r300_translate_vertex_shader(r300, vs, vs->state.tokens);
} else {
- return draw_create_vertex_shader(r300->draw, shader);
+ vs->draw_vs = draw_create_vertex_shader(r300->draw, shader);
}
+
+ return vs;
}
static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
- if (r300_screen(pipe->screen)->caps->has_tcl) {
- struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
-
- if (vs == NULL) {
- r300->vs_state.state = NULL;
- return;
- } else if (!vs->translated) {
- r300_translate_vertex_shader(r300, vs);
- }
+ if (vs == NULL) {
+ r300->vs_state.state = NULL;
+ return;
+ }
+ if (vs == r300->vs_state.state) {
+ return;
+ }
+ r300->vs_state.state = vs;
- UPDATE_STATE(shader, r300->vs_state);
- r300->vs_state.size = vs->code.length + 9;
+ // VS output mapping for HWTCL or stream mapping for SWTCL to the RS block
+ if (r300->fs.state) {
+ r300_vertex_shader_setup_wpos(r300);
+ }
+ memcpy(r300->vap_output_state.state, &vs->vap_out,
+ sizeof(struct r300_vap_output_state));
+ r300->vap_output_state.dirty = TRUE;
- r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */
- r300->vap_output_state.dirty = TRUE;
- r300->vertex_stream_state.dirty = TRUE; /* XXX needed for TCL bypass */
- r300->pvs_flush.dirty = TRUE;
+ /* The majority of the RS block bits is dependent on the vertex shader. */
+ r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */
- if (r300->fs) {
- r300_vertex_shader_setup_wpos(r300);
+ if (r300->screen->caps.has_tcl) {
+ r300->vs_state.dirty = TRUE;
+ r300->vs_state.size =
+ vs->code.length + 9 +
+ (vs->immediates_count ? vs->immediates_count * 4 + 3 : 0);
+
+ if (vs->externals_count) {
+ r300->vs_constants.dirty = TRUE;
+ r300->vs_constants.size = vs->externals_count * 4 + 3;
+ } else {
+ r300->vs_constants.size = 0;
}
- r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS;
+ r300->pvs_flush.dirty = TRUE;
} else {
draw_flush(r300->draw);
draw_bind_vertex_shader(r300->draw,
- (struct draw_vertex_shader*)shader);
+ (struct draw_vertex_shader*)vs->draw_vs);
}
}
static void r300_delete_vs_state(struct pipe_context* pipe, void* shader)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
- if (r300_screen(pipe->screen)->caps->has_tcl) {
- struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
-
+ if (r300->screen->caps.has_tcl) {
rc_constants_destroy(&vs->code.constants);
- FREE((void*)vs->state.tokens);
- FREE(shader);
} else {
draw_delete_vertex_shader(r300->draw,
- (struct draw_vertex_shader*)shader);
+ (struct draw_vertex_shader*)vs->draw_vs);
}
+
+ FREE((void*)vs->state.tokens);
+ FREE(shader);
}
static void r300_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- struct pipe_buffer *buf)
+ struct pipe_resource *buf)
{
struct r300_context* r300 = r300_context(pipe);
- struct r300_screen *r300screen = r300_screen(pipe->screen);
+ struct r300_constant_buffer *cbuf;
+ struct pipe_transfer *tr;
void *mapped;
int max_size = 0;
- if (buf == NULL || buf->size == 0 ||
- (mapped = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_READ)) == NULL)
- {
- r300->shader_constants[shader].count = 0;
- return;
- }
-
- assert((buf->size % 4 * sizeof(float)) == 0);
-
- /* Check the size of the constant buffer. */
switch (shader) {
case PIPE_SHADER_VERTEX:
+ cbuf = (struct r300_constant_buffer*)r300->vs_constants.state;
max_size = 256;
break;
case PIPE_SHADER_FRAGMENT:
- if (r300screen->caps->is_r500) {
+ cbuf = (struct r300_constant_buffer*)r300->fs_constants.state;
+ if (r300->screen->caps.is_r500) {
max_size = 256;
- /* XXX Implement emission of r400's extended constant buffer. */
- /*} else if (r300screen->caps->is_r400) {
- max_size = 64;*/
} else {
max_size = 32;
}
break;
default:
assert(0);
+ return;
}
+ if (buf == NULL || buf->width0 == 0 ||
+ (mapped = pipe_buffer_map(pipe, buf, PIPE_TRANSFER_READ, &tr)) == NULL)
+ {
+ cbuf->count = 0;
+ return;
+ }
+
+ assert((buf->width0 % 4 * sizeof(float)) == 0);
+
+ /* Check the size of the constant buffer. */
/* XXX Subtract immediates and RC_STATE_* variables. */
- if (buf->size > (sizeof(float) * 4 * max_size)) {
- debug_printf("r300: Max size of the constant buffer is "
+ if (buf->width0 > (sizeof(float) * 4 * max_size)) {
+ fprintf(stderr, "r300: Max size of the constant buffer is "
"%i*4 floats.\n", max_size);
abort();
}
- memcpy(r300->shader_constants[shader].constants, mapped, buf->size);
- r300->shader_constants[shader].count = buf->size / (4 * sizeof(float));
- pipe_buffer_unmap(pipe->screen, buf);
+ memcpy(cbuf->constants, mapped, buf->width0);
+ cbuf->count = buf->width0 / (4 * sizeof(float));
+ pipe_buffer_unmap(pipe, buf, tr);
if (shader == PIPE_SHADER_VERTEX) {
- r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS;
- r300->pvs_flush.dirty = TRUE;
+ if (r300->screen->caps.has_tcl) {
+ if (r300->vs_constants.size) {
+ r300->vs_constants.dirty = TRUE;
+ }
+ r300->pvs_flush.dirty = TRUE;
+ } else if (r300->draw) {
+ draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX,
+ 0, cbuf->constants,
+ buf->width0);
+ }
+ } else if (shader == PIPE_SHADER_FRAGMENT) {
+ r300->fs_constants.dirty = TRUE;
}
- else if (shader == PIPE_SHADER_FRAGMENT)
- r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
}
void r300_init_state_functions(struct r300_context* r300)
@@ -1243,14 +1507,19 @@ void r300_init_state_functions(struct r300_context* r300)
r300->context.bind_vertex_sampler_states = r300_lacks_vertex_textures;
r300->context.delete_sampler_state = r300_delete_sampler_state;
- r300->context.set_fragment_sampler_textures = r300_set_sampler_textures;
+ r300->context.set_fragment_sampler_views = r300_set_fragment_sampler_views;
+ r300->context.create_sampler_view = r300_create_sampler_view;
+ r300->context.sampler_view_destroy = r300_sampler_view_destroy;
r300->context.set_scissor_state = r300_set_scissor_state;
r300->context.set_viewport_state = r300_set_viewport_state;
r300->context.set_vertex_buffers = r300_set_vertex_buffers;
- r300->context.set_vertex_elements = r300_set_vertex_elements;
+
+ r300->context.create_vertex_elements_state = r300_create_vertex_elements_state;
+ r300->context.bind_vertex_elements_state = r300_bind_vertex_elements_state;
+ r300->context.delete_vertex_elements_state = r300_delete_vertex_elements_state;
r300->context.create_vs_state = r300_create_vs_state;
r300->context.bind_vs_state = r300_bind_vs_state;
diff --git a/src/gallium/drivers/r300/r300_state.h b/src/gallium/drivers/r300/r300_state.h
new file mode 100644
index 0000000000..1d557506cf
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_state.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 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"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_STATE_H
+#define R300_STATE_H
+
+struct r300_context;
+
+void r300_mark_fs_code_dirty(struct r300_context *r300);
+
+#endif /* R300_STATE_H */
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index 9c8e907fdf..46c192eae1 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -30,6 +30,7 @@
#include "r300_fs.h"
#include "r300_screen.h"
#include "r300_shader_semantics.h"
+#include "r300_state.h"
#include "r300_state_derived.h"
#include "r300_state_inlines.h"
#include "r300_vs.h"
@@ -37,6 +38,12 @@
/* r300_state_derived: Various bits of state which are dependent upon
* currently bound CSO data. */
+enum r300_rs_swizzle {
+ SWIZ_XYZW = 0,
+ SWIZ_X001,
+ SWIZ_XY01,
+};
+
static void r300_draw_emit_attrib(struct r300_context* r300,
enum attrib_emit emit,
enum interp_mode interp,
@@ -83,8 +90,10 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300)
/* XXX Back-face colors. */
/* Texture coordinates. */
+ /* Only 8 generic vertex attributes can be used. If there are more,
+ * they won't be rasterized. */
gen_count = 0;
- for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
+ for (i = 0; i < ATTR_GENERIC_COUNT && gen_count < 8; i++) {
if (vs_outputs->generic[i] != ATTR_UNUSED) {
r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE,
vs_outputs->generic[i]);
@@ -93,84 +102,26 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300)
}
/* Fog coordinates. */
- if (vs_outputs->fog != ATTR_UNUSED) {
+ if (gen_count < 8 && vs_outputs->fog != ATTR_UNUSED) {
r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE,
vs_outputs->fog);
gen_count++;
}
-
- /* XXX magic */
- assert(gen_count <= 8);
-}
-
-/* Update the PSC tables. */
-/* XXX move this function into r300_state.c after TCL-bypass gets removed
- * XXX because this one is dependent only on vertex elements. */
-static void r300_vertex_psc(struct r300_context* r300)
-{
- struct r300_vertex_shader* vs = r300->vs_state.state;
- struct r300_vertex_stream_state *vformat =
- (struct r300_vertex_stream_state*)r300->vertex_stream_state.state;
- uint16_t type, swizzle;
- enum pipe_format format;
- unsigned i;
- int identity[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
- int* stream_tab;
-
- memset(vformat, 0, sizeof(struct r300_vertex_stream_state));
-
- stream_tab = identity;
-
- /* Vertex shaders have no semantics on their inputs,
- * so PSC should just route stuff based on the vertex elements,
- * and not on attrib information. */
- DBG(r300, DBG_DRAW, "r300: vs expects %d attribs, routing %d elements"
- " in psc\n",
- vs->info.num_inputs,
- r300->vertex_element_count);
-
- for (i = 0; i < r300->vertex_element_count; i++) {
- format = r300->vertex_element[i].src_format;
-
- type = r300_translate_vertex_data_type(format) |
- (stream_tab[i] << R300_DST_VEC_LOC_SHIFT);
- swizzle = r300_translate_vertex_data_swizzle(format);
-
- if (i & 1) {
- vformat->vap_prog_stream_cntl[i >> 1] |= type << 16;
- vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16;
- } else {
- vformat->vap_prog_stream_cntl[i >> 1] |= type;
- vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle;
- }
- }
-
- assert(i <= 15);
-
- /* Set the last vector in the PSC. */
- if (i) {
- i -= 1;
- }
- vformat->vap_prog_stream_cntl[i >> 1] |=
- (R300_LAST_VEC << (i & 1 ? 16 : 0));
-
- vformat->count = (i >> 1) + 1;
- r300->vertex_stream_state.size = (1 + vformat->count) * 2;
}
/* Update the PSC tables for SW TCL, using Draw. */
-static void r300_swtcl_vertex_psc(struct r300_context* r300)
+static void r300_swtcl_vertex_psc(struct r300_context *r300)
{
+ struct r300_vertex_stream_state *vstream = r300->vertex_stream_state.state;
struct r300_vertex_shader* vs = r300->vs_state.state;
- struct r300_vertex_stream_state *vformat =
- (struct r300_vertex_stream_state*)r300->vertex_stream_state.state;
struct vertex_info* vinfo = &r300->vertex_info;
uint16_t type, swizzle;
enum pipe_format format;
unsigned i, attrib_count;
int* vs_output_tab = vs->stream_loc_notcl;
- memset(vformat, 0, sizeof(struct r300_vertex_stream_state));
+ /* XXX hax */
+ memset(vstream, 0, sizeof(struct r300_vertex_stream_state));
/* For each Draw attribute, route it to the fragment shader according
* to the vs_output_tab. */
@@ -181,9 +132,7 @@ static void r300_swtcl_vertex_psc(struct r300_context* r300)
" vs_output_tab %d\n", vinfo->attrib[i].src_index,
vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit,
vs_output_tab[i]);
- }
- for (i = 0; i < attrib_count; i++) {
/* Make sure we have a proper destination for our attribute. */
assert(vs_output_tab[i] != -1);
@@ -199,11 +148,11 @@ static void r300_swtcl_vertex_psc(struct r300_context* r300)
/* Add the attribute to the PSC table. */
if (i & 1) {
- vformat->vap_prog_stream_cntl[i >> 1] |= type << 16;
- vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16;
+ vstream->vap_prog_stream_cntl[i >> 1] |= type << 16;
+ vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16;
} else {
- vformat->vap_prog_stream_cntl[i >> 1] |= type;
- vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle;
+ vstream->vap_prog_stream_cntl[i >> 1] |= type;
+ vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle;
}
}
@@ -211,11 +160,12 @@ static void r300_swtcl_vertex_psc(struct r300_context* r300)
if (i) {
i -= 1;
}
- vformat->vap_prog_stream_cntl[i >> 1] |=
+ vstream->vap_prog_stream_cntl[i >> 1] |=
(R300_LAST_VEC << (i & 1 ? 16 : 0));
- vformat->count = (i >> 1) + 1;
- r300->vertex_stream_state.size = (1 + vformat->count) * 2;
+ vstream->count = (i >> 1) + 1;
+ r300->vertex_stream_state.dirty = TRUE;
+ r300->vertex_stream_state.size = (1 + vstream->count) * 2;
}
static void r300_rs_col(struct r300_rs_block* rs, int id, int ptr,
@@ -237,14 +187,20 @@ static void r300_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset)
}
static void r300_rs_tex(struct r300_rs_block* rs, int id, int ptr,
- boolean swizzle_X001)
+ enum r300_rs_swizzle swiz)
{
- if (swizzle_X001) {
+ if (swiz == SWIZ_X001) {
rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) |
R300_RS_SEL_S(R300_RS_SEL_C0) |
R300_RS_SEL_T(R300_RS_SEL_K0) |
R300_RS_SEL_R(R300_RS_SEL_K0) |
R300_RS_SEL_Q(R300_RS_SEL_K1);
+ } else if (swiz == SWIZ_XY01) {
+ rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) |
+ R300_RS_SEL_S(R300_RS_SEL_C0) |
+ R300_RS_SEL_T(R300_RS_SEL_C1) |
+ R300_RS_SEL_R(R300_RS_SEL_K0) |
+ R300_RS_SEL_Q(R300_RS_SEL_K1);
} else {
rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) |
R300_RS_SEL_S(R300_RS_SEL_C0) |
@@ -280,15 +236,20 @@ static void r500_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset)
}
static void r500_rs_tex(struct r300_rs_block* rs, int id, int ptr,
- boolean swizzle_X001)
+ enum r300_rs_swizzle swiz)
{
int rs_tex_comp = ptr*4;
- if (swizzle_X001) {
+ if (swiz == SWIZ_X001) {
rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) |
R500_RS_SEL_T(R500_RS_IP_PTR_K0) |
R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
R500_RS_SEL_Q(R500_RS_IP_PTR_K1);
+ } else if (swiz == SWIZ_XY01) {
+ rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) |
+ R500_RS_SEL_T(rs_tex_comp + 1) |
+ R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
+ R500_RS_SEL_Q(R500_RS_IP_PTR_K1);
} else {
rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) |
R500_RS_SEL_T(rs_tex_comp + 1) |
@@ -317,12 +278,12 @@ static void r300_update_rs_block(struct r300_context* r300,
int i, col_count = 0, tex_count = 0, fp_offset = 0, count;
void (*rX00_rs_col)(struct r300_rs_block*, int, int, boolean);
void (*rX00_rs_col_write)(struct r300_rs_block*, int, int);
- void (*rX00_rs_tex)(struct r300_rs_block*, int, int, boolean);
+ void (*rX00_rs_tex)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
void (*rX00_rs_tex_write)(struct r300_rs_block*, int, int);
boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
vs_outputs->bcolor[1] != ATTR_UNUSED;
- if (r300_screen(r300->context.screen)->caps->is_r500) {
+ if (r300->screen->caps.is_r500) {
rX00_rs_col = r500_rs_col;
rX00_rs_col_write = r500_rs_col_write;
rX00_rs_tex = r500_rs_tex;
@@ -359,14 +320,19 @@ static void r300_update_rs_block(struct r300_context* r300,
/* Rasterize texture coordinates. */
for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
- if (vs_outputs->generic[i] != ATTR_UNUSED) {
+ bool sprite_coord = !!(r300->sprite_coord_enable & (1 << i));
+
+ if (vs_outputs->generic[i] != ATTR_UNUSED || sprite_coord) {
/* Always rasterize if it's written by the VS,
* otherwise it locks up. */
- rX00_rs_tex(&rs, tex_count, tex_count, FALSE);
+ rX00_rs_tex(&rs, tex_count, tex_count,
+ sprite_coord ? SWIZ_XY01 : SWIZ_XYZW);
/* Write it to the FS input register if it's used by the FS. */
if (fs_inputs->generic[i] != ATTR_UNUSED) {
rX00_rs_tex_write(&rs, tex_count, fp_offset);
+ if (sprite_coord)
+ debug_printf("r300: SpriteCoord (generic index %i) is being written to reg %i\n", i, fp_offset);
fp_offset++;
}
tex_count++;
@@ -383,7 +349,7 @@ static void r300_update_rs_block(struct r300_context* r300,
if (vs_outputs->fog != ATTR_UNUSED) {
/* Always rasterize if it's written by the VS,
* otherwise it locks up. */
- rX00_rs_tex(&rs, tex_count, tex_count, TRUE);
+ rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_X001);
/* Write it to the FS input register if it's used by the FS. */
if (fs_inputs->fog != ATTR_UNUSED) {
@@ -401,8 +367,8 @@ static void r300_update_rs_block(struct r300_context* r300,
/* Rasterize WPOS. */
/* If the FS doesn't need it, it's not written by the VS. */
- if (fs_inputs->wpos != ATTR_UNUSED) {
- rX00_rs_tex(&rs, tex_count, tex_count, FALSE);
+ if (vs_outputs->wpos != ATTR_UNUSED && fs_inputs->wpos != ATTR_UNUSED) {
+ rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_XYZW);
rX00_rs_tex_write(&rs, tex_count, fp_offset);
fp_offset++;
@@ -432,23 +398,8 @@ static void r300_update_rs_block(struct r300_context* r300,
static void r300_update_derived_shader_state(struct r300_context* r300)
{
struct r300_vertex_shader* vs = r300->vs_state.state;
- struct r300_screen* r300screen = r300_screen(r300->context.screen);
- struct r300_vap_output_state *vap_out =
- (struct r300_vap_output_state*)r300->vap_output_state.state;
- /* XXX Mmm, delicious hax */
- memset(&r300->vertex_info, 0, sizeof(struct vertex_info));
- memcpy(vap_out, vs->hwfmt, sizeof(uint)*4);
-
- r300_update_rs_block(r300, &vs->outputs, &r300->fs->inputs);
-
- if (r300screen->caps->has_tcl) {
- r300_vertex_psc(r300);
- } else {
- r300_draw_emit_all_attribs(r300);
- draw_compute_vertex_size(&r300->vertex_info);
- r300_swtcl_vertex_psc(r300);
- }
+ r300_update_rs_block(r300, &vs->outputs, &r300_fs(r300)->shader->inputs);
}
static boolean r300_dsa_writes_depth_stencil(struct r300_dsa_state* dsa)
@@ -508,12 +459,12 @@ static void r300_update_ztop(struct r300_context* r300)
/* ZS writes */
if (r300_dsa_writes_depth_stencil(r300->dsa_state.state) &&
- (r300_dsa_alpha_test_enabled(r300->dsa_state.state) ||/* (1) */
- r300->fs->info.uses_kill)) { /* (2) */
+ (r300_dsa_alpha_test_enabled(r300->dsa_state.state) || /* (1) */
+ r300_fs(r300)->shader->info.uses_kill)) { /* (2) */
ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
- } else if (r300_fragment_shader_writes_depth(r300->fs)) { /* (5) */
+ } else if (r300_fragment_shader_writes_depth(r300_fs(r300))) { /* (5) */
ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
- } else if (r300->query_current) { /* (6) */
+ } else if (r300->query_current) { /* (6) */
ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
} else {
ztop_state->z_buffer_top = R300_ZTOP_ENABLE;
@@ -528,48 +479,71 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
(struct r300_textures_state*)r300->textures_state.state;
struct r300_texture_sampler_state *texstate;
struct r300_sampler_state *sampler;
+ struct r300_sampler_view *view;
struct r300_texture *tex;
unsigned min_level, max_level, i, size;
- unsigned count = MIN2(state->texture_count, state->sampler_count);
+ unsigned count = MIN2(state->sampler_view_count,
+ state->sampler_state_count);
state->tx_enable = 0;
+ state->count = 0;
size = 2;
for (i = 0; i < count; i++) {
- if (state->textures[i] && state->sampler_states[i]) {
+ if (state->sampler_views[i] && state->sampler_states[i]) {
state->tx_enable |= 1 << i;
- tex = state->textures[i];
+ view = state->sampler_views[i];
+ tex = r300_texture(view->base.texture);
sampler = state->sampler_states[i];
texstate = &state->regs[i];
- memcpy(texstate->format, &tex->state, sizeof(uint32_t)*3);
- texstate->filter[0] = sampler->filter0;
- texstate->filter[1] = sampler->filter1;
+ texstate->format = view->format;
+ texstate->filter0 = sampler->filter0;
+ texstate->filter1 = sampler->filter1;
texstate->border_color = sampler->border_color;
- texstate->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) |
- R300_TXO_MICRO_TILE(tex->microtile);
/* to emulate 1D textures through 2D ones correctly */
- if (tex->tex.target == PIPE_TEXTURE_1D) {
- texstate->filter[0] &= ~R300_TX_WRAP_T_MASK;
- texstate->filter[0] |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
+ if (tex->b.b.target == PIPE_TEXTURE_1D) {
+ texstate->filter0 &= ~R300_TX_WRAP_T_MASK;
+ texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
}
- if (tex->is_npot) {
+ if (tex->uses_pitch) {
/* NPOT textures don't support mip filter, unfortunately.
* This prevents incorrect rendering. */
- texstate->filter[0] &= ~R300_TX_MIN_FILTER_MIP_MASK;
+ texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK;
+
+ /* Mask out the mirrored flag. */
+ if (texstate->filter0 & R300_TX_WRAP_S(R300_TX_MIRRORED)) {
+ texstate->filter0 &= ~R300_TX_WRAP_S(R300_TX_MIRRORED);
+ }
+ if (texstate->filter0 & R300_TX_WRAP_T(R300_TX_MIRRORED)) {
+ texstate->filter0 &= ~R300_TX_WRAP_T(R300_TX_MIRRORED);
+ }
+
+ /* Change repeat to clamp-to-edge.
+ * (the repeat bit has a value of 0, no masking needed). */
+ if ((texstate->filter0 & R300_TX_WRAP_S_MASK) ==
+ R300_TX_WRAP_S(R300_TX_REPEAT)) {
+ texstate->filter0 |= R300_TX_WRAP_S(R300_TX_CLAMP_TO_EDGE);
+ }
+ if ((texstate->filter0 & R300_TX_WRAP_T_MASK) ==
+ R300_TX_WRAP_T(R300_TX_REPEAT)) {
+ texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
+ }
} else {
/* determine min/max levels */
/* the MAX_MIP level is the largest (finest) one */
- max_level = MIN2(sampler->max_lod, tex->tex.last_level);
- min_level = MIN2(sampler->min_lod, max_level);
- texstate->format[0] |= R300_TX_NUM_LEVELS(max_level);
- texstate->filter[0] |= R300_TX_MAX_MIP_LEVEL(min_level);
+ max_level = MIN3(sampler->max_lod + view->base.first_level,
+ tex->b.b.last_level, view->base.last_level);
+ min_level = MIN2(sampler->min_lod + view->base.first_level,
+ max_level);
+ texstate->format.format0 |= R300_TX_NUM_LEVELS(max_level);
+ texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level);
}
- texstate->filter[0] |= i << 28;
+ texstate->filter0 |= i << 28;
size += 16;
state->count = i+1;
@@ -577,18 +551,31 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
}
r300->textures_state.size = size;
+
+ /* Pick a fragment shader based on either the texture compare state
+ * or the uses_pitch flag. */
+ if (r300->fs.state && count) {
+ if (r300_pick_fragment_shader(r300)) {
+ r300_mark_fs_code_dirty(r300);
+ }
+ }
}
void r300_update_derived_state(struct r300_context* r300)
{
- if (r300->rs_block_state.dirty ||
- r300->vertex_stream_state.dirty || /* XXX put updating this state out of this file */
- r300->rs_state.dirty) { /* XXX and remove this one (tcl_bypass dependency) */
+ if (r300->textures_state.dirty) {
+ r300_merge_textures_and_samplers(r300);
+ }
+
+ if (r300->rs_block_state.dirty) {
r300_update_derived_shader_state(r300);
}
- if (r300->textures_state.dirty) {
- r300_merge_textures_and_samplers(r300);
+ if (r300->draw) {
+ memset(&r300->vertex_info, 0, sizeof(struct vertex_info));
+ r300_draw_emit_all_attribs(r300);
+ draw_compute_vertex_size(&r300->vertex_info);
+ r300_swtcl_vertex_psc(r300);
}
r300_update_ztop(r300);
diff --git a/src/gallium/drivers/r300/r300_state_derived.h b/src/gallium/drivers/r300/r300_state_derived.h
index 05ad535e2d..71a4a47b00 100644
--- a/src/gallium/drivers/r300/r300_state_derived.h
+++ b/src/gallium/drivers/r300/r300_state_derived.h
@@ -25,10 +25,6 @@
struct r300_context;
-unsigned r300_shader_key_hash(void* key);
-
-int r300_shader_key_compare(void* key1, void* key2);
-
void r300_update_derived_state(struct r300_context* r300);
#endif /* R300_STATE_DERIVED_H */
diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h
index af7827820c..480d0f7c4a 100644
--- a/src/gallium/drivers/r300/r300_state_inlines.h
+++ b/src/gallium/drivers/r300/r300_state_inlines.h
@@ -32,6 +32,8 @@
#include "r300_reg.h"
+#include <stdio.h>
+
/* Some maths. These should probably find their way to u_math, if needed. */
static INLINE int pack_float_16_6x(float f) {
@@ -54,7 +56,7 @@ static INLINE uint32_t r300_translate_blend_function(int blend_func)
case PIPE_BLEND_MAX:
return R300_COMB_FCN_MAX;
default:
- debug_printf("r300: Unknown blend function %d\n", blend_func);
+ fprintf(stderr, "r300: Unknown blend function %d\n", blend_func);
assert(0);
break;
}
@@ -100,13 +102,13 @@ static INLINE uint32_t r300_translate_blend_factor(int blend_fact)
case PIPE_BLENDFACTOR_SRC1_ALPHA:
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
- debug_printf("r300: Implementation error: "
+ fprintf(stderr, "r300: Implementation error: "
"Bad blend factor %d not supported!\n", blend_fact);
assert(0);
break;
default:
- debug_printf("r300: Unknown blend factor %d\n", blend_fact);
+ fprintf(stderr, "r300: Unknown blend factor %d\n", blend_fact);
assert(0);
break;
}
@@ -135,7 +137,7 @@ static INLINE uint32_t r300_translate_depth_stencil_function(int zs_func)
case PIPE_FUNC_ALWAYS:
return R300_ZS_ALWAYS;
default:
- debug_printf("r300: Unknown depth/stencil function %d\n",
+ fprintf(stderr, "r300: Unknown depth/stencil function %d\n",
zs_func);
assert(0);
break;
@@ -163,7 +165,7 @@ static INLINE uint32_t r300_translate_stencil_op(int s_op)
case PIPE_STENCIL_OP_INVERT:
return R300_ZS_INVERT;
default:
- debug_printf("r300: Unknown stencil op %d", s_op);
+ fprintf(stderr, "r300: Unknown stencil op %d", s_op);
assert(0);
break;
}
@@ -190,7 +192,7 @@ static INLINE uint32_t r300_translate_alpha_function(int alpha_func)
case PIPE_FUNC_ALWAYS:
return R300_FG_ALPHA_FUNC_ALWAYS;
default:
- debug_printf("r300: Unknown alpha function %d", alpha_func);
+ fprintf(stderr, "r300: Unknown alpha function %d", alpha_func);
assert(0);
break;
}
@@ -209,7 +211,7 @@ r300_translate_polygon_mode_front(unsigned mode) {
return R300_GA_POLY_MODE_FRONT_PTYPE_POINT;
default:
- debug_printf("r300: Bad polygon mode %i in %s\n", mode,
+ fprintf(stderr, "r300: Bad polygon mode %i in %s\n", mode,
__FUNCTION__);
return R300_GA_POLY_MODE_FRONT_PTYPE_TRI;
}
@@ -227,7 +229,7 @@ r300_translate_polygon_mode_back(unsigned mode) {
return R300_GA_POLY_MODE_BACK_PTYPE_POINT;
default:
- debug_printf("r300: Bad polygon mode %i in %s\n", mode,
+ fprintf(stderr, "r300: Bad polygon mode %i in %s\n", mode,
__FUNCTION__);
return R300_GA_POLY_MODE_BACK_PTYPE_TRI;
}
@@ -253,9 +255,9 @@ static INLINE uint32_t r300_translate_wrap(int wrap)
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
- return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED;
+ return R300_TX_CLAMP_TO_BORDER | R300_TX_MIRRORED;
default:
- debug_printf("r300: Unknown texture wrap %d", wrap);
+ fprintf(stderr, "r300: Unknown texture wrap %d", wrap);
assert(0);
return 0;
}
@@ -276,7 +278,7 @@ static INLINE uint32_t r300_translate_tex_filters(int min, int mag, int mip,
retval |= R300_TX_MIN_FILTER_LINEAR;
break;
default:
- debug_printf("r300: Unknown texture filter %d\n", min);
+ fprintf(stderr, "r300: Unknown texture filter %d\n", min);
assert(0);
break;
}
@@ -288,7 +290,7 @@ static INLINE uint32_t r300_translate_tex_filters(int min, int mag, int mip,
retval |= R300_TX_MAG_FILTER_LINEAR;
break;
default:
- debug_printf("r300: Unknown texture filter %d\n", mag);
+ fprintf(stderr, "r300: Unknown texture filter %d\n", mag);
assert(0);
break;
}
@@ -304,7 +306,7 @@ static INLINE uint32_t r300_translate_tex_filters(int min, int mag, int mip,
retval |= R300_TX_MIN_FILTER_MIP_LINEAR;
break;
default:
- debug_printf("r300: Unknown texture filter %d\n", mip);
+ fprintf(stderr, "r300: Unknown texture filter %d\n", mip);
assert(0);
break;
}
@@ -327,6 +329,18 @@ static INLINE uint32_t r300_anisotropy(unsigned max_aniso)
}
}
+static INLINE uint32_t r500_anisotropy(unsigned max_aniso)
+{
+ if (!max_aniso) {
+ return 0;
+ }
+ max_aniso -= 1;
+
+ // Map the range [0, 15] to [0, 63].
+ return R500_TX_MAX_ANISO(MIN2((unsigned)(max_aniso*4.2001), 63)) |
+ R500_TX_ANISO_HIGH_QUALITY;
+}
+
/* Non-CSO state. (For now.) */
static INLINE uint32_t r300_translate_gb_pipes(int pipe_count)
@@ -348,44 +362,16 @@ static INLINE uint32_t r300_translate_gb_pipes(int pipe_count)
return 0;
}
-/* Utility function to count the number of components in RGBAZS formats.
- * XXX should go to util or p_format.h */
-static INLINE unsigned pf_component_count(enum pipe_format format) {
- unsigned count = 0;
-
- if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0)) {
- count++;
- }
- if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 1)) {
- count++;
- }
- if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 2)) {
- count++;
- }
- if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 3)) {
- count++;
- }
- if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) {
- count++;
- }
- if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) {
- count++;
- }
-
- return count;
-}
-
/* Translate pipe_formats into PSC vertex types. */
static INLINE uint16_t
r300_translate_vertex_data_type(enum pipe_format format) {
uint32_t result = 0;
const struct util_format_description *desc;
- unsigned components = pf_component_count(format);
desc = util_format_description(format);
if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
- debug_printf("r300: Bad format %s in %s:%d\n", util_format_name(format),
+ fprintf(stderr, "r300: Bad format %s in %s:%d\n", util_format_name(format),
__FUNCTION__, __LINE__);
assert(0);
}
@@ -393,20 +379,20 @@ r300_translate_vertex_data_type(enum pipe_format format) {
switch (desc->channel[0].type) {
/* Half-floats, floats, doubles */
case UTIL_FORMAT_TYPE_FLOAT:
- switch (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0)) {
+ switch (desc->channel[0].size) {
case 16:
/* XXX Supported only on RV350 and later. */
- if (components > 2) {
+ if (desc->nr_channels > 2) {
result = R300_DATA_TYPE_FLT16_4;
} else {
result = R300_DATA_TYPE_FLT16_2;
}
break;
case 32:
- result = R300_DATA_TYPE_FLOAT_1 + (components - 1);
+ result = R300_DATA_TYPE_FLOAT_1 + (desc->nr_channels - 1);
break;
default:
- debug_printf("r300: Bad format %s in %s:%d\n",
+ fprintf(stderr, "r300: Bad format %s in %s:%d\n",
util_format_name(format), __FUNCTION__, __LINE__);
assert(0);
}
@@ -415,27 +401,27 @@ r300_translate_vertex_data_type(enum pipe_format format) {
case UTIL_FORMAT_TYPE_UNSIGNED:
/* Signed ints */
case UTIL_FORMAT_TYPE_SIGNED:
- switch (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0)) {
+ switch (desc->channel[0].size) {
case 8:
result = R300_DATA_TYPE_BYTE;
break;
case 16:
- if (components > 2) {
+ if (desc->nr_channels > 2) {
result = R300_DATA_TYPE_SHORT_4;
} else {
result = R300_DATA_TYPE_SHORT_2;
}
break;
default:
- debug_printf("r300: Bad format %s in %s:%d\n",
+ fprintf(stderr, "r300: Bad format %s in %s:%d\n",
util_format_name(format), __FUNCTION__, __LINE__);
- debug_printf("r300: util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) == %d\n",
- util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0));
+ fprintf(stderr, "r300: desc->channel[0].size == %d\n",
+ desc->channel[0].size);
assert(0);
}
break;
default:
- debug_printf("r300: Bad format %s in %s:%d\n",
+ fprintf(stderr, "r300: Bad format %s in %s:%d\n",
util_format_name(format), __FUNCTION__, __LINE__);
assert(0);
}
@@ -457,7 +443,7 @@ r300_translate_vertex_data_swizzle(enum pipe_format format) {
assert(format);
if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
- debug_printf("r300: Bad format %s in %s:%d\n",
+ fprintf(stderr, "r300: Bad format %s in %s:%d\n",
util_format_name(format), __FUNCTION__, __LINE__);
return 0;
}
diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c
index 4a2c68269b..ffb175febf 100644
--- a/src/gallium/drivers/r300/r300_state_invariant.c
+++ b/src/gallium/drivers/r300/r300_state_invariant.c
@@ -41,16 +41,12 @@ struct pipe_viewport_state r300_viewport_identity = {
void r300_emit_invariant_state(struct r300_context* r300,
unsigned size, void* state)
{
- struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps;
+ struct r300_capabilities* caps = &r300_screen(r300->context.screen)->caps;
CS_LOCALS(r300);
- BEGIN_CS(14 + (caps->has_tcl ? 2: 0));
+ BEGIN_CS(12 + (caps->has_tcl ? 2: 0));
/*** Graphics Backend (GB) ***/
- /* Various GB enables */
- OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
- R300_GB_LINE_STUFF_ENABLE |
- R300_GB_TRIANGLE_STUFF_ENABLE);
/* Subpixel multisampling for AA
* These are commented out because glisse's CS checker doesn't like them.
* I presume these will be re-enabled later.
@@ -78,7 +74,7 @@ void r300_emit_invariant_state(struct r300_context* r300,
END_CS;
/* XXX unsorted stuff from surface_fill */
- BEGIN_CS(44 + (caps->has_tcl ? 7 : 0) +
+ BEGIN_CS(38 + (caps->has_tcl ? 7 : 0) +
(caps->family >= CHIP_FAMILY_RV350 ? 4 : 0));
if (caps->has_tcl) {
@@ -90,11 +86,6 @@ void r300_emit_invariant_state(struct r300_context* r300,
OUT_CS_32F(1.0);
OUT_CS_32F(1.0);
}
- /* XXX point tex stuffing */
- OUT_CS_REG_SEQ(R300_GA_POINT_S0, 1);
- OUT_CS_32F(0.0);
- OUT_CS_REG_SEQ(R300_GA_POINT_S1, 1);
- OUT_CS_32F(1.0);
/* XXX line tex stuffing */
OUT_CS_REG_SEQ(R300_GA_LINE_S0, 1);
OUT_CS_32F(0.0);
@@ -125,9 +116,5 @@ void r300_emit_invariant_state(struct r300_context* r300,
OUT_CS_REG(R300_ZB_DEPTHCLEARVALUE, 0x00000000);
OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0x00000000);
OUT_CS_REG(R300_ZB_HIZ_PITCH, 0x00000000);
-
- /* XXX */
- OUT_CS_REG(R300_SC_CLIP_RULE, 0xaaaa);
-
END_CS;
}
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index c0144f64b4..e795c8df0b 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -28,11 +28,14 @@
#include "util/u_memory.h"
#include "r300_context.h"
+#include "r300_reg.h"
#include "r300_texture.h"
+#include "r300_transfer.h"
#include "r300_screen.h"
-#include "r300_state_inlines.h"
+#include "r300_winsys.h"
-#include "radeon_winsys.h"
+/* XXX Enable float textures here. */
+/*#define ENABLE_FLOAT_TEXTURES*/
#define TILE_WIDTH 0
#define TILE_HEIGHT 1
@@ -46,6 +49,18 @@ static const unsigned microblock_table[5][3][2] = {
{{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */
};
+/* Return true for non-compressed and non-YUV formats. */
+static boolean r300_format_is_plain(enum pipe_format format)
+{
+ const struct util_format_description *desc = util_format_description(format);
+
+ if (!format) {
+ return FALSE;
+ }
+
+ return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN;
+}
+
/* Translate a pipe_format into a useful texture format for sampling.
*
* Some special formats are translated directly using R300_EASY_TX_FORMAT,
@@ -58,11 +73,12 @@ static const unsigned microblock_table[5][3][2] = {
*
* The FORMAT specifies how the texture sampler will treat the texture, and
* makes available X, Y, Z, W, ZERO, and ONE for swizzling. */
-static uint32_t r300_translate_texformat(enum pipe_format format)
+uint32_t r300_translate_texformat(enum pipe_format format,
+ const unsigned char *swizzle)
{
uint32_t result = 0;
const struct util_format_description *desc;
- unsigned components = 0, i;
+ unsigned i;
boolean uniform = TRUE;
const uint32_t swizzle_shift[4] = {
R300_TX_FORMAT_R_SHIFT,
@@ -70,7 +86,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
R300_TX_FORMAT_B_SHIFT,
R300_TX_FORMAT_A_SHIFT
};
- const uint32_t swizzle[4] = {
+ const uint32_t swizzle_bit[4] = {
R300_TX_FORMAT_X,
R300_TX_FORMAT_Y,
R300_TX_FORMAT_Z,
@@ -93,7 +109,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
case PIPE_FORMAT_Z16_UNORM:
return R300_EASY_TX_FORMAT(X, X, X, X, X16);
case PIPE_FORMAT_X8Z24_UNORM:
- case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP);
default:
return ~0; /* Unsupported. */
@@ -117,24 +133,50 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
result |= R300_TX_FORMAT_GAMMA;
break;
- default:;
+ default:
+ switch (format) {
+ /* Same as YUV but without the YUR->RGB conversion. */
+ case PIPE_FORMAT_R8G8_B8G8_UNORM:
+ return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result;
+ case PIPE_FORMAT_G8R8_G8B8_UNORM:
+ return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result;
+ default:;
+ }
}
/* Add swizzle. */
+ if (!swizzle) {
+ swizzle = desc->swizzle;
+ } /*else {
+ if (swizzle[0] != desc->swizzle[0] ||
+ swizzle[1] != desc->swizzle[1] ||
+ swizzle[2] != desc->swizzle[2] ||
+ swizzle[3] != desc->swizzle[3])
+ {
+ const char n[6] = "RGBA01";
+ fprintf(stderr, "Got different swizzling! Format: %c%c%c%c, "
+ "View: %c%c%c%c\n",
+ n[desc->swizzle[0]], n[desc->swizzle[1]],
+ n[desc->swizzle[2]], n[desc->swizzle[3]],
+ n[swizzle[0]], n[swizzle[1]], n[swizzle[2]],
+ n[swizzle[3]]);
+ }
+ }*/
+
for (i = 0; i < 4; i++) {
- switch (desc->swizzle[i]) {
+ switch (swizzle[i]) {
case UTIL_FORMAT_SWIZZLE_X:
case UTIL_FORMAT_SWIZZLE_NONE:
- result |= swizzle[0] << swizzle_shift[i];
+ result |= swizzle_bit[0] << swizzle_shift[i];
break;
case UTIL_FORMAT_SWIZZLE_Y:
- result |= swizzle[1] << swizzle_shift[i];
+ result |= swizzle_bit[1] << swizzle_shift[i];
break;
case UTIL_FORMAT_SWIZZLE_Z:
- result |= swizzle[2] << swizzle_shift[i];
+ result |= swizzle_bit[2] << swizzle_shift[i];
break;
case UTIL_FORMAT_SWIZZLE_W:
- result |= swizzle[3] << swizzle_shift[i];
+ result |= swizzle_bit[3] << swizzle_shift[i];
break;
case UTIL_FORMAT_SWIZZLE_0:
result |= R300_TX_FORMAT_ZERO << swizzle_shift[i];
@@ -147,8 +189,8 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
}
}
- /* Compressed formats. */
- if (desc->layout == UTIL_FORMAT_LAYOUT_COMPRESSED) {
+ /* S3TC formats. */
+ if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
switch (format) {
case PIPE_FORMAT_DXT1_RGB:
case PIPE_FORMAT_DXT1_RGBA:
@@ -166,28 +208,42 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
}
}
- /* Get the number of components. */
- for (i = 0; i < 4; i++) {
- if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
- ++components;
- }
- }
-
/* Add sign. */
- for (i = 0; i < components; i++) {
+ for (i = 0; i < desc->nr_channels; i++) {
if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
result |= sign_bit[i];
}
}
+ /* This is truly a special format.
+ * It stores R8G8 and B is computed using sqrt(1 - R^2 - G^2)
+ * in the sampler unit. Also known as D3DFMT_CxV8U8. */
+ if (format == PIPE_FORMAT_R8G8Bx_SNORM) {
+ return R300_TX_FORMAT_CxV8U8 | result;
+ }
+
+ /* RGTC formats. */
+ if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
+ switch (format) {
+ case PIPE_FORMAT_RGTC1_UNORM:
+ case PIPE_FORMAT_RGTC1_SNORM:
+ return R500_TX_FORMAT_ATI1N | result;
+ case PIPE_FORMAT_RGTC2_UNORM:
+ case PIPE_FORMAT_RGTC2_SNORM:
+ return R400_TX_FORMAT_ATI2N | result;
+ default:
+ return ~0; /* Unsupported/unknown. */
+ }
+ }
+
/* See whether the components are of the same size. */
- for (i = 1; i < components; i++) {
+ for (i = 1; i < desc->nr_channels; i++) {
uniform = uniform && desc->channel[0].size == desc->channel[i].size;
}
/* Non-uniform formats. */
if (!uniform) {
- switch (components) {
+ switch (desc->nr_channels) {
case 3:
if (desc->channel[0].size == 5 &&
desc->channel[1].size == 6 &&
@@ -229,7 +285,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
switch (desc->channel[0].size) {
case 4:
- switch (components) {
+ switch (desc->nr_channels) {
case 2:
return R300_TX_FORMAT_Y4X4 | result;
case 4:
@@ -238,7 +294,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
return ~0;
case 8:
- switch (components) {
+ switch (desc->nr_channels) {
case 1:
return R300_TX_FORMAT_X8 | result;
case 2:
@@ -249,7 +305,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
return ~0;
case 16:
- switch (components) {
+ switch (desc->nr_channels) {
case 1:
return R300_TX_FORMAT_X16 | result;
case 2:
@@ -260,12 +316,11 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
}
return ~0;
-/* XXX Enable float textures here. */
-#if 0
+#if defined(ENABLE_FLOAT_TEXTURES)
case UTIL_FORMAT_TYPE_FLOAT:
switch (desc->channel[0].size) {
case 16:
- switch (components) {
+ switch (desc->nr_channels) {
case 1:
return R300_TX_FORMAT_16F | result;
case 2:
@@ -276,7 +331,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
return ~0;
case 32:
- switch (components) {
+ switch (desc->nr_channels) {
case 1:
return R300_TX_FORMAT_32F | result;
case 2:
@@ -291,6 +346,17 @@ static uint32_t r300_translate_texformat(enum pipe_format format)
return ~0; /* Unsupported/unknown. */
}
+uint32_t r500_tx_format_msb_bit(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_RGTC1_UNORM:
+ case PIPE_FORMAT_RGTC1_SNORM:
+ return R500_TXFORMAT_MSB;
+ default:
+ return 0;
+ }
+}
+
/* Buffer formats. */
/* Colorbuffer formats. This is the unswizzled format of the RB3D block's
@@ -302,7 +368,6 @@ static uint32_t r300_translate_colorformat(enum pipe_format format)
case PIPE_FORMAT_A8_UNORM:
case PIPE_FORMAT_I8_UNORM:
case PIPE_FORMAT_L8_UNORM:
- case PIPE_FORMAT_L8_SRGB:
case PIPE_FORMAT_R8_UNORM:
case PIPE_FORMAT_R8_SNORM:
return R300_COLOR_FORMAT_I8;
@@ -310,39 +375,43 @@ static uint32_t r300_translate_colorformat(enum pipe_format format)
/* 16-bit buffers. */
case PIPE_FORMAT_B5G6R5_UNORM:
return R300_COLOR_FORMAT_RGB565;
+
case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
return R300_COLOR_FORMAT_ARGB1555;
+
case PIPE_FORMAT_B4G4R4A4_UNORM:
+ case PIPE_FORMAT_B4G4R4X4_UNORM:
return R300_COLOR_FORMAT_ARGB4444;
/* 32-bit buffers. */
case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_SRGB:
case PIPE_FORMAT_B8G8R8X8_UNORM:
- case PIPE_FORMAT_B8G8R8X8_SRGB:
case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_A8R8G8B8_SRGB:
case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_X8R8G8B8_SRGB:
case PIPE_FORMAT_A8B8G8R8_UNORM:
case PIPE_FORMAT_R8G8B8A8_SNORM:
- case PIPE_FORMAT_A8B8G8R8_SRGB:
case PIPE_FORMAT_X8B8G8R8_UNORM:
- case PIPE_FORMAT_X8B8G8R8_SRGB:
+ case PIPE_FORMAT_R8G8B8X8_UNORM:
case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
return R300_COLOR_FORMAT_ARGB8888;
+
case PIPE_FORMAT_R10G10B10A2_UNORM:
+ case PIPE_FORMAT_R10G10B10X2_SNORM:
+ case PIPE_FORMAT_B10G10R10A2_UNORM:
+ case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
return R500_COLOR_FORMAT_ARGB2101010; /* R5xx-only? */
/* 64-bit buffers. */
case PIPE_FORMAT_R16G16B16A16_UNORM:
case PIPE_FORMAT_R16G16B16A16_SNORM:
- //case PIPE_FORMAT_R16G16B16A16_FLOAT: /* not in pipe_format */
+#if defined(ENABLE_FLOAT_TEXTURES)
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+#endif
return R300_COLOR_FORMAT_ARGB16161616;
-/* XXX Enable float textures here. */
-#if 0
/* 128-bit buffers. */
+#if defined(ENABLE_FLOAT_TEXTURES)
case PIPE_FORMAT_R32G32B32A32_FLOAT:
return R300_COLOR_FORMAT_ARGB32323232;
#endif
@@ -367,7 +436,7 @@ static uint32_t r300_translate_zsformat(enum pipe_format format)
/* 24-bit depth, ignored stencil */
case PIPE_FORMAT_X8Z24_UNORM:
/* 24-bit depth, 8-bit stencil */
- case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
return R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
default:
return ~0; /* Unsupported. */
@@ -393,12 +462,7 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format)
desc = util_format_description(format);
/* Specifies how the shader output is written to the fog unit. */
- if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
- /* The gamma correction causes precision loss so we need
- * higher precision to maintain reasonable quality.
- * It has nothing to do with the colorbuffer format. */
- modifier |= R300_US_OUT_FMT_C4_10_GAMMA;
- } else if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) {
+ if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) {
if (desc->channel[0].size == 32) {
modifier |= R300_US_OUT_FMT_C4_32_FP;
} else {
@@ -428,46 +492,44 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format)
return modifier | R300_C2_SEL_A;
case PIPE_FORMAT_I8_UNORM:
case PIPE_FORMAT_L8_UNORM:
- case PIPE_FORMAT_L8_SRGB:
case PIPE_FORMAT_R8_UNORM:
case PIPE_FORMAT_R8_SNORM:
return modifier | R300_C2_SEL_R;
- /* ARGB 32-bit outputs. */
+ /* BGRA outputs. */
case PIPE_FORMAT_B5G6R5_UNORM:
case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
case PIPE_FORMAT_B4G4R4A4_UNORM:
+ case PIPE_FORMAT_B4G4R4X4_UNORM:
case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_SRGB:
case PIPE_FORMAT_B8G8R8X8_UNORM:
- case PIPE_FORMAT_B8G8R8X8_SRGB:
+ case PIPE_FORMAT_B10G10R10A2_UNORM:
return modifier |
R300_C0_SEL_B | R300_C1_SEL_G |
R300_C2_SEL_R | R300_C3_SEL_A;
- /* BGRA 32-bit outputs. */
+ /* ARGB outputs. */
case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_A8R8G8B8_SRGB:
case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_X8R8G8B8_SRGB:
return modifier |
R300_C0_SEL_A | R300_C1_SEL_R |
R300_C2_SEL_G | R300_C3_SEL_B;
- /* RGBA 32-bit outputs. */
+ /* ABGR outputs. */
case PIPE_FORMAT_A8B8G8R8_UNORM:
- case PIPE_FORMAT_R8G8B8A8_SNORM:
- case PIPE_FORMAT_A8B8G8R8_SRGB:
case PIPE_FORMAT_X8B8G8R8_UNORM:
- case PIPE_FORMAT_X8B8G8R8_SRGB:
return modifier |
R300_C0_SEL_A | R300_C1_SEL_B |
R300_C2_SEL_G | R300_C3_SEL_R;
- /* ABGR 32-bit outputs. */
+ /* RGBA outputs. */
+ case PIPE_FORMAT_R8G8B8X8_UNORM:
+ case PIPE_FORMAT_R8G8B8A8_SNORM:
case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
case PIPE_FORMAT_R10G10B10A2_UNORM:
- /* RGBA high precision outputs (same swizzles as ABGR low precision) */
+ case PIPE_FORMAT_R10G10B10X2_SNORM:
+ case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
case PIPE_FORMAT_R16G16B16A16_UNORM:
case PIPE_FORMAT_R16G16B16A16_SNORM:
//case PIPE_FORMAT_R16G16B16A16_FLOAT: /* not in pipe_format */
@@ -494,74 +556,83 @@ boolean r300_is_zs_format_supported(enum pipe_format format)
boolean r300_is_sampler_format_supported(enum pipe_format format)
{
- return r300_translate_texformat(format) != ~0;
+ return r300_translate_texformat(format, 0) != ~0;
}
-static void r300_setup_texture_state(struct r300_screen* screen, struct r300_texture* tex)
+static void r300_texture_setup_immutable_state(struct r300_screen* screen,
+ struct r300_texture* tex)
{
- struct r300_texture_format_state* state = &tex->state;
- struct pipe_texture *pt = &tex->tex;
- unsigned i;
- boolean is_r500 = screen->caps->is_r500;
+ struct r300_texture_format_state* f = &tex->tx_format;
+ struct pipe_resource *pt = &tex->b.b;
+ boolean is_r500 = screen->caps.is_r500;
/* Set sampler state. */
- state->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) |
- R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff);
+ f->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) |
+ R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff);
- if (tex->is_npot) {
+ if (tex->uses_pitch) {
/* rectangles love this */
- state->format0 |= R300_TX_PITCH_EN;
- state->format2 = (tex->pitch[0] - 1) & 0x1fff;
+ f->format0 |= R300_TX_PITCH_EN;
+ f->format2 = (tex->pitch[0] - 1) & 0x1fff;
} else {
/* power of two textures (3D, mipmaps, and no pitch) */
- state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf);
+ f->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf);
}
- state->format1 = r300_translate_texformat(pt->format);
+ f->format1 = 0;
if (pt->target == PIPE_TEXTURE_CUBE) {
- state->format1 |= R300_TX_FORMAT_CUBIC_MAP;
+ f->format1 |= R300_TX_FORMAT_CUBIC_MAP;
}
if (pt->target == PIPE_TEXTURE_3D) {
- state->format1 |= R300_TX_FORMAT_3D;
+ f->format1 |= R300_TX_FORMAT_3D;
}
/* large textures on r500 */
if (is_r500)
{
if (pt->width0 > 2048) {
- state->format2 |= R500_TXWIDTH_BIT11;
+ f->format2 |= R500_TXWIDTH_BIT11;
}
if (pt->height0 > 2048) {
- state->format2 |= R500_TXHEIGHT_BIT11;
+ f->format2 |= R500_TXHEIGHT_BIT11;
}
}
+ f->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) |
+ R300_TXO_MICRO_TILE(tex->microtile);
+
SCREEN_DBG(screen, DBG_TEX, "r300: Set texture state (%dx%d, %d levels)\n",
pt->width0, pt->height0, pt->last_level);
+}
+
+static void r300_texture_setup_fb_state(struct r300_screen* screen,
+ struct r300_texture* tex)
+{
+ unsigned i;
/* Set framebuffer state. */
- if (util_format_is_depth_or_stencil(tex->tex.format)) {
- for (i = 0; i <= tex->tex.last_level; i++) {
+ if (util_format_is_depth_or_stencil(tex->b.b.format)) {
+ for (i = 0; i <= tex->b.b.last_level; i++) {
tex->fb_state.depthpitch[i] =
tex->pitch[i] |
R300_DEPTHMACROTILE(tex->mip_macrotile[i]) |
R300_DEPTHMICROTILE(tex->microtile);
}
- tex->fb_state.zb_format = r300_translate_zsformat(tex->tex.format);
+ tex->fb_state.zb_format = r300_translate_zsformat(tex->b.b.format);
} else {
- for (i = 0; i <= tex->tex.last_level; i++) {
+ for (i = 0; i <= tex->b.b.last_level; i++) {
tex->fb_state.colorpitch[i] =
tex->pitch[i] |
- r300_translate_colorformat(tex->tex.format) |
+ r300_translate_colorformat(tex->b.b.format) |
R300_COLOR_TILE(tex->mip_macrotile[i]) |
R300_COLOR_MICROTILE(tex->microtile);
}
- tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->tex.format);
+ tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->b.b.format);
}
}
void r300_texture_reinterpret_format(struct pipe_screen *screen,
- struct pipe_texture *tex,
+ struct pipe_resource *tex,
enum pipe_format new_format)
{
struct r300_screen *r300screen = r300_screen(screen);
@@ -571,7 +642,7 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen,
tex->format = new_format;
- r300_setup_texture_state(r300_screen(screen), (struct r300_texture*)tex);
+ r300_texture_setup_fb_state(r300_screen(screen), r300_texture(tex));
}
unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
@@ -579,7 +650,7 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
{
unsigned offset = tex->offset[level];
- switch (tex->tex.target) {
+ switch (tex->b.b.target) {
case PIPE_TEXTURE_3D:
assert(face == 0);
return offset + zslice * tex->layer_size[level];
@@ -603,7 +674,7 @@ static unsigned r300_texture_get_tile_size(struct r300_texture* tex,
{
unsigned pixsize, tile_size;
- pixsize = util_format_get_blocksize(tex->tex.format);
+ pixsize = util_format_get_blocksize(tex->b.b.format);
tile_size = microblock_table[util_logbase2(pixsize)][tex->microtile][dim];
if (macrotile) {
@@ -617,18 +688,23 @@ static unsigned r300_texture_get_tile_size(struct r300_texture* tex,
/* Return true if macrotiling should be enabled on the miplevel. */
static boolean r300_texture_macro_switch(struct r300_texture *tex,
unsigned level,
- boolean rv350_mode)
+ boolean rv350_mode,
+ int dim)
{
- unsigned tile_width, width;
+ unsigned tile, texdim;
- tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH, TRUE);
- width = u_minify(tex->tex.width0, level);
+ tile = r300_texture_get_tile_size(tex, dim, TRUE);
+ if (dim == TILE_WIDTH) {
+ texdim = u_minify(tex->b.b.width0, level);
+ } else {
+ texdim = u_minify(tex->b.b.height0, level);
+ }
/* See TX_FILTER1_n.MACRO_SWITCH. */
if (rv350_mode) {
- return width >= tile_width;
+ return texdim >= tile;
} else {
- return width > tile_width;
+ return texdim > tile;
}
}
@@ -645,22 +721,22 @@ unsigned r300_texture_get_stride(struct r300_screen* screen,
return tex->stride_override;
/* Check the level. */
- if (level > tex->tex.last_level) {
+ if (level > tex->b.b.last_level) {
SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n",
- __FUNCTION__, level, tex->tex.last_level);
+ __FUNCTION__, level, tex->b.b.last_level);
return 0;
}
- width = u_minify(tex->tex.width0, level);
+ width = u_minify(tex->b.b.width0, level);
- if (!util_format_is_compressed(tex->tex.format)) {
+ if (r300_format_is_plain(tex->b.b.format)) {
tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH,
tex->mip_macrotile[level]);
width = align(width, tile_width);
- return util_format_get_stride(tex->tex.format, width);
+ return util_format_get_stride(tex->b.b.format, width);
} else {
- return align(util_format_get_stride(tex->tex.format, width), 32);
+ return align(util_format_get_stride(tex->b.b.format, width), 32);
}
}
@@ -669,32 +745,60 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture* tex,
{
unsigned height, tile_height;
- height = u_minify(tex->tex.height0, level);
+ height = u_minify(tex->b.b.height0, level);
- if (!util_format_is_compressed(tex->tex.format)) {
+ if (r300_format_is_plain(tex->b.b.format)) {
tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT,
tex->mip_macrotile[level]);
height = align(height, tile_height);
+
+ /* This is needed for the kernel checker, unfortunately. */
+ height = util_next_power_of_two(height);
}
- return util_format_get_nblocksy(tex->tex.format, height);
+ return util_format_get_nblocksy(tex->b.b.format, height);
+}
+
+static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen,
+ struct r300_texture *tex)
+{
+ /* The kernels <= 2.6.34-rc3 compute the size of mipmapped 3D textures
+ * incorrectly. This is a workaround to prevent CS from being rejected. */
+
+ unsigned i, size;
+
+ if (screen->rws->get_value(screen->rws, R300_VID_TEX3D_MIP_BUG) &&
+ tex->b.b.target == PIPE_TEXTURE_3D &&
+ tex->b.b.last_level > 0) {
+ size = 0;
+
+ for (i = 0; i <= tex->b.b.last_level; i++) {
+ size += r300_texture_get_stride(screen, tex, i) *
+ r300_texture_get_nblocksy(tex, i);
+ }
+
+ size *= tex->b.b.depth0;
+ tex->size = size;
+ }
}
static void r300_setup_miptree(struct r300_screen* screen,
struct r300_texture* tex)
{
- struct pipe_texture* base = &tex->tex;
+ struct pipe_resource* base = &tex->b.b;
unsigned stride, size, layer_size, nblocksy, i;
- boolean rv350_mode = screen->caps->family >= CHIP_FAMILY_RV350;
+ boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_RV350;
SCREEN_DBG(screen, DBG_TEX, "r300: Making miptree for texture, format %s\n",
util_format_name(base->format));
for (i = 0; i <= base->last_level; i++) {
/* Let's see if this miplevel can be macrotiled. */
- tex->mip_macrotile[i] = (tex->macrotile == R300_BUFFER_TILED &&
- r300_texture_macro_switch(tex, i, rv350_mode)) ?
- R300_BUFFER_TILED : R300_BUFFER_LINEAR;
+ tex->mip_macrotile[i] =
+ (tex->macrotile == R300_BUFFER_TILED &&
+ r300_texture_macro_switch(tex, i, rv350_mode, TILE_WIDTH) &&
+ r300_texture_macro_switch(tex, i, rv350_mode, TILE_HEIGHT)) ?
+ R300_BUFFER_TILED : R300_BUFFER_LINEAR;
stride = r300_texture_get_stride(screen, tex, i);
nblocksy = r300_texture_get_nblocksy(tex, i);
@@ -720,64 +824,163 @@ static void r300_setup_miptree(struct r300_screen* screen,
static void r300_setup_flags(struct r300_texture* tex)
{
- tex->is_npot = !util_is_power_of_two(tex->tex.width0) ||
- !util_is_power_of_two(tex->tex.height0);
+ tex->uses_pitch = !util_is_power_of_two(tex->b.b.width0) ||
+ !util_is_power_of_two(tex->b.b.height0) ||
+ tex->stride_override;
+}
+
+static void r300_setup_tiling(struct pipe_screen *screen,
+ struct r300_texture *tex)
+{
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
+ enum pipe_format format = tex->b.b.format;
+ boolean rv350_mode = r300_screen(screen)->caps.family >= CHIP_FAMILY_RV350;
+ boolean is_zb = util_format_is_depth_or_stencil(format);
+ boolean dbg_no_tiling = SCREEN_DBG_ON(r300_screen(screen), DBG_NO_TILING);
+
+ if (!r300_format_is_plain(format)) {
+ return;
+ }
+
+ /* If height == 1, disable microtiling except for zbuffer. */
+ if (!is_zb && (tex->b.b.height0 == 1 || dbg_no_tiling)) {
+ return;
+ }
+
+ /* Set microtiling. */
+ switch (util_format_get_blocksize(format)) {
+ case 1:
+ case 4:
+ tex->microtile = R300_BUFFER_TILED;
+ break;
+
+ case 2:
+ case 8:
+ if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) {
+ tex->microtile = R300_BUFFER_SQUARETILED;
+ }
+ break;
+ }
+
+ if (dbg_no_tiling) {
+ return;
+ }
+
+ /* Set macrotiling. */
+ if (r300_texture_macro_switch(tex, 0, rv350_mode, TILE_WIDTH) &&
+ r300_texture_macro_switch(tex, 0, rv350_mode, TILE_HEIGHT)) {
+ tex->macrotile = R300_BUFFER_TILED;
+ }
+}
+
+static unsigned r300_texture_is_referenced(struct pipe_context *context,
+ struct pipe_resource *texture,
+ unsigned face, unsigned level)
+{
+ struct r300_context *r300 = r300_context(context);
+ struct r300_texture *rtex = (struct r300_texture *)texture;
+
+ if (r300->rws->is_buffer_referenced(r300->rws, rtex->buffer, R300_REF_CS))
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+
+ return PIPE_UNREFERENCED;
}
+static void r300_texture_destroy(struct pipe_screen *screen,
+ struct pipe_resource* texture)
+{
+ struct r300_texture* tex = (struct r300_texture*)texture;
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys;
+
+ rws->buffer_reference(rws, &tex->buffer, NULL);
+ FREE(tex);
+}
+
+static boolean r300_texture_get_handle(struct pipe_screen* screen,
+ struct pipe_resource *texture,
+ struct winsys_handle *whandle)
+{
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
+ struct r300_texture* tex = (struct r300_texture*)texture;
+ unsigned stride;
+
+ if (!tex) {
+ return FALSE;
+ }
+
+ stride = r300_texture_get_stride(r300_screen(screen), tex, 0);
+
+ rws->buffer_get_handle(rws, tex->buffer, stride, whandle);
+
+ return TRUE;
+}
+
+struct u_resource_vtbl r300_texture_vtbl =
+{
+ r300_texture_get_handle, /* get_handle */
+ r300_texture_destroy, /* resource_destroy */
+ r300_texture_is_referenced, /* is_resource_referenced */
+ r300_texture_get_transfer, /* get_transfer */
+ r300_texture_transfer_destroy, /* transfer_destroy */
+ r300_texture_transfer_map, /* transfer_map */
+ u_default_transfer_flush_region, /* transfer_flush_region */
+ r300_texture_transfer_unmap, /* transfer_unmap */
+ u_default_transfer_inline_write /* transfer_inline_write */
+};
+
/* Create a new texture. */
-static struct pipe_texture*
- r300_texture_create(struct pipe_screen* screen,
- const struct pipe_texture* template)
+struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
+ const struct pipe_resource* base)
{
struct r300_texture* tex = CALLOC_STRUCT(r300_texture);
struct r300_screen* rscreen = r300_screen(screen);
- struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys;
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
if (!tex) {
return NULL;
}
- tex->tex = *template;
- pipe_reference_init(&tex->tex.reference, 1);
- tex->tex.screen = screen;
+ tex->b.b = *base;
+ tex->b.vtbl = &r300_texture_vtbl;
+ pipe_reference_init(&tex->b.b.reference, 1);
+ tex->b.b.screen = screen;
r300_setup_flags(tex);
+ if (!(base->flags & R300_RESOURCE_FLAG_TRANSFER) &&
+ !(base->bind & PIPE_BIND_SCANOUT)) {
+ r300_setup_tiling(screen, tex);
+ }
r300_setup_miptree(rscreen, tex);
- r300_setup_texture_state(rscreen, tex);
-
- tex->buffer = screen->buffer_create(screen, 2048,
- PIPE_BUFFER_USAGE_PIXEL,
- tex->size);
- winsys->buffer_set_tiling(winsys, tex->buffer,
- tex->pitch[0],
- tex->microtile != R300_BUFFER_LINEAR,
- tex->macrotile != R300_BUFFER_LINEAR);
+ r300_texture_3d_fix_mipmapping(rscreen, tex);
+ r300_texture_setup_immutable_state(rscreen, tex);
+ r300_texture_setup_fb_state(rscreen, tex);
+
+ tex->buffer = rws->buffer_create(rws, 2048,
+ PIPE_BIND_SAMPLER_VIEW, /* XXX */
+ tex->size);
+ rws->buffer_set_tiling(rws, tex->buffer,
+ tex->pitch[0],
+ tex->microtile,
+ tex->macrotile);
if (!tex->buffer) {
FREE(tex);
return NULL;
}
- return (struct pipe_texture*)tex;
-}
-
-static void r300_texture_destroy(struct pipe_texture* texture)
-{
- struct r300_texture* tex = (struct r300_texture*)texture;
-
- pipe_buffer_reference(&tex->buffer, NULL);
-
- FREE(tex);
+ return (struct pipe_resource*)tex;
}
-static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
- struct pipe_texture* texture,
- unsigned face,
- unsigned level,
- unsigned zslice,
- unsigned flags)
+/* Not required to implement u_resource_vtbl, consider moving to another file:
+ */
+struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
+ struct pipe_resource* texture,
+ unsigned face,
+ unsigned level,
+ unsigned zslice,
+ unsigned flags)
{
- struct r300_texture* tex = (struct r300_texture*)texture;
+ struct r300_texture* tex = r300_texture(texture);
struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface);
unsigned offset;
@@ -785,7 +988,7 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
if (surface) {
pipe_reference_init(&surface->reference, 1);
- pipe_texture_reference(&surface->texture, texture);
+ pipe_resource_reference(&surface->texture, texture);
surface->format = texture->format;
surface->width = u_minify(texture->width0, level);
surface->height = u_minify(texture->height0, level);
@@ -800,20 +1003,25 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
return surface;
}
-static void r300_tex_surface_destroy(struct pipe_surface* s)
+/* Not required to implement u_resource_vtbl, consider moving to another file:
+ */
+void r300_tex_surface_destroy(struct pipe_surface* s)
{
- pipe_texture_reference(&s->texture, NULL);
+ pipe_resource_reference(&s->texture, NULL);
FREE(s);
}
-static struct pipe_texture*
- r300_texture_blanket(struct pipe_screen* screen,
- const struct pipe_texture* base,
- const unsigned* stride,
- struct pipe_buffer* buffer)
+struct pipe_resource*
+r300_texture_from_handle(struct pipe_screen* screen,
+ const struct pipe_resource* base,
+ struct winsys_handle *whandle)
{
- struct r300_texture* tex;
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys;
struct r300_screen* rscreen = r300_screen(screen);
+ struct r300_winsys_buffer *buffer;
+ struct r300_texture* tex;
+ unsigned stride;
+ boolean override_zb_flags;
/* Support only 2D textures without mipmaps */
if (base->target != PIPE_TEXTURE_2D ||
@@ -822,101 +1030,60 @@ static struct pipe_texture*
return NULL;
}
+ buffer = rws->buffer_from_handle(rws, screen, whandle, &stride);
+ if (!buffer) {
+ return NULL;
+ }
+
tex = CALLOC_STRUCT(r300_texture);
if (!tex) {
return NULL;
}
- tex->tex = *base;
- pipe_reference_init(&tex->tex.reference, 1);
- tex->tex.screen = screen;
+ tex->b.b = *base;
+ tex->b.vtbl = &r300_texture_vtbl;
+ pipe_reference_init(&tex->b.b.reference, 1);
+ tex->b.b.screen = screen;
- tex->stride_override = *stride;
- tex->pitch[0] = *stride / util_format_get_blocksize(base->format);
+ tex->stride_override = stride;
- r300_setup_flags(tex);
- r300_setup_texture_state(rscreen, tex);
+ /* one ref already taken */
+ tex->buffer = buffer;
- pipe_buffer_reference(&tex->buffer, buffer);
+ rws->buffer_get_tiling(rws, buffer, &tex->microtile, &tex->macrotile);
+ r300_setup_flags(tex);
- return (struct pipe_texture*)tex;
-}
+ /* Enforce microtiled zbuffer. */
+ override_zb_flags = util_format_is_depth_or_stencil(base->format) &&
+ tex->microtile == R300_BUFFER_LINEAR;
-static struct pipe_video_surface *
-r300_video_surface_create(struct pipe_screen *screen,
- enum pipe_video_chroma_format chroma_format,
- unsigned width, unsigned height)
-{
- struct r300_video_surface *r300_vsfc;
- struct pipe_texture template;
-
- assert(screen);
- assert(width && height);
-
- r300_vsfc = CALLOC_STRUCT(r300_video_surface);
- if (!r300_vsfc)
- return NULL;
-
- pipe_reference_init(&r300_vsfc->base.reference, 1);
- r300_vsfc->base.screen = screen;
- r300_vsfc->base.chroma_format = chroma_format;
- r300_vsfc->base.width = width;
- r300_vsfc->base.height = height;
-
- memset(&template, 0, sizeof(struct pipe_texture));
- template.target = PIPE_TEXTURE_2D;
- template.format = PIPE_FORMAT_B8G8R8X8_UNORM;
- template.last_level = 0;
- template.width0 = util_next_power_of_two(width);
- template.height0 = util_next_power_of_two(height);
- template.depth0 = 1;
- template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER |
- PIPE_TEXTURE_USAGE_RENDER_TARGET;
-
- r300_vsfc->tex = screen->texture_create(screen, &template);
- if (!r300_vsfc->tex)
- {
- FREE(r300_vsfc);
- return NULL;
- }
-
- return &r300_vsfc->base;
-}
-
-static void r300_video_surface_destroy(struct pipe_video_surface *vsfc)
-{
- struct r300_video_surface *r300_vsfc = r300_video_surface(vsfc);
- pipe_texture_reference(&r300_vsfc->tex, NULL);
- FREE(r300_vsfc);
-}
+ if (override_zb_flags) {
+ switch (util_format_get_blocksize(base->format)) {
+ case 4:
+ tex->microtile = R300_BUFFER_TILED;
+ break;
-void r300_init_screen_texture_functions(struct pipe_screen* screen)
-{
- screen->texture_create = r300_texture_create;
- screen->texture_destroy = r300_texture_destroy;
- screen->get_tex_surface = r300_get_tex_surface;
- screen->tex_surface_destroy = r300_tex_surface_destroy;
- screen->texture_blanket = r300_texture_blanket;
-
- screen->video_surface_create = r300_video_surface_create;
- screen->video_surface_destroy= r300_video_surface_destroy;
-}
+ case 2:
+ if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) {
+ tex->microtile = R300_BUFFER_SQUARETILED;
+ break;
+ }
+ /* Pass through. */
-boolean r300_get_texture_buffer(struct pipe_screen* screen,
- struct pipe_texture* texture,
- struct pipe_buffer** buffer,
- unsigned* stride)
-{
- struct r300_texture* tex = (struct r300_texture*)texture;
- if (!tex) {
- return FALSE;
+ default:
+ override_zb_flags = FALSE;
+ }
}
- pipe_buffer_reference(buffer, tex->buffer);
-
- if (stride) {
- *stride = r300_texture_get_stride(r300_screen(screen), tex, 0);
+ r300_setup_miptree(rscreen, tex);
+ r300_texture_setup_immutable_state(rscreen, tex);
+ r300_texture_setup_fb_state(rscreen, tex);
+
+ if (override_zb_flags) {
+ rws->buffer_set_tiling(rws, tex->buffer,
+ tex->pitch[0],
+ tex->microtile,
+ tex->macrotile);
}
-
- return TRUE;
+ return (struct pipe_resource*)tex;
}
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index 46a5fb6188..453d42b188 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -23,14 +23,14 @@
#ifndef R300_TEXTURE_H
#define R300_TEXTURE_H
-#include "pipe/p_video_state.h"
#include "util/u_format.h"
-#include "r300_reg.h"
-
struct r300_texture;
-void r300_init_screen_texture_functions(struct pipe_screen* screen);
+uint32_t r300_translate_texformat(enum pipe_format format,
+ const unsigned char *swizzle);
+
+uint32_t r500_tx_format_msb_bit(enum pipe_format format);
unsigned r300_texture_get_stride(struct r300_screen* screen,
struct r300_texture* tex, unsigned level);
@@ -39,7 +39,7 @@ 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,
+ struct pipe_resource *tex,
enum pipe_format new_format);
boolean r300_is_colorbuffer_format_supported(enum pipe_format format);
@@ -48,25 +48,24 @@ boolean r300_is_zs_format_supported(enum pipe_format format);
boolean r300_is_sampler_format_supported(enum pipe_format format);
-struct r300_video_surface
-{
- struct pipe_video_surface base;
- struct pipe_texture *tex;
-};
-static INLINE struct r300_video_surface *
-r300_video_surface(struct pipe_video_surface *pvs)
-{
- return (struct r300_video_surface *)pvs;
-}
+struct pipe_resource*
+r300_texture_from_handle(struct pipe_screen* screen,
+ const struct pipe_resource* base,
+ struct winsys_handle *whandle);
+
+struct pipe_resource*
+r300_texture_create(struct pipe_screen* screen,
+ const struct pipe_resource* templ);
-#ifndef R300_WINSYS_H
-boolean r300_get_texture_buffer(struct pipe_screen* screen,
- struct pipe_texture* texture,
- struct pipe_buffer** buffer,
- unsigned* stride);
+struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
+ struct pipe_resource* texture,
+ unsigned face,
+ unsigned level,
+ unsigned zslice,
+ unsigned flags);
-#endif /* R300_WINSYS_H */
+void r300_tex_surface_destroy(struct pipe_surface* s);
#endif /* R300_TEXTURE_H */
diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
index aff4ddd4e2..f6428ed760 100644
--- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c
+++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
@@ -25,12 +25,11 @@
#include "radeon_compiler.h"
#include "radeon_program.h"
+#include "tgsi/tgsi_info.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_scan.h"
#include "tgsi/tgsi_util.h"
-#include "util/u_debug.h"
-
static unsigned translate_opcode(unsigned opcode)
{
switch(opcode) {
@@ -116,10 +115,10 @@ static unsigned translate_opcode(unsigned opcode)
/* case TGSI_OPCODE_ENDREP: return RC_OPCODE_ENDREP; */
/* case TGSI_OPCODE_PUSHA: return RC_OPCODE_PUSHA; */
/* case TGSI_OPCODE_POPA: return RC_OPCODE_POPA; */
- /* case TGSI_OPCODE_CEIL: return RC_OPCODE_CEIL; */
+ case TGSI_OPCODE_CEIL: return RC_OPCODE_CEIL;
/* case TGSI_OPCODE_I2F: return RC_OPCODE_I2F; */
/* case TGSI_OPCODE_NOT: return RC_OPCODE_NOT; */
- /* case TGSI_OPCODE_TRUNC: return RC_OPCODE_TRUNC; */
+ case TGSI_OPCODE_TRUNC: return RC_OPCODE_FLR;
/* case TGSI_OPCODE_SHL: return RC_OPCODE_SHL; */
/* case TGSI_OPCODE_ISHR: return RC_OPCODE_SHR; */
/* case TGSI_OPCODE_AND: return RC_OPCODE_AND; */
@@ -145,7 +144,7 @@ static unsigned translate_opcode(unsigned opcode)
case TGSI_OPCODE_KIL: return RC_OPCODE_KIL;
}
- debug_printf("r300: Unknown TGSI/RC opcode: %i\n", opcode);
+ fprintf(stderr, "r300: Unknown TGSI/RC opcode: %s\n", tgsi_get_opcode_name(opcode));
return RC_OPCODE_ILLEGAL_OPCODE;
}
@@ -272,9 +271,6 @@ static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_inst
struct rc_instruction * dst;
int i;
- if (src->Instruction.Opcode == TGSI_OPCODE_END)
- return;
-
dst = rc_insert_new_instruction(ttr->compiler, ttr->compiler->Program.Instructions.Prev);
dst->U.I.Opcode = translate_opcode(src->Instruction.Opcode);
dst->U.I.SaturateMode = translate_saturate(src->Instruction.Saturate);
@@ -333,6 +329,7 @@ static void handle_immediate(struct tgsi_to_rc * ttr,
void r300_tgsi_to_rc(struct tgsi_to_rc * ttr,
const struct tgsi_token * tokens)
{
+ struct tgsi_full_instruction *inst;
struct tgsi_parse_context parser;
unsigned imm_index = 0;
int i;
@@ -367,7 +364,15 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr,
imm_index++;
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
- transform_instruction(ttr, &parser.FullToken.FullInstruction);
+ inst = &parser.FullToken.FullInstruction;
+ /* This hack with the RET opcode woudn't work with
+ * conditionals. */
+ if (inst->Instruction.Opcode == TGSI_OPCODE_END ||
+ inst->Instruction.Opcode == TGSI_OPCODE_RET) {
+ break;
+ }
+
+ transform_instruction(ttr, inst);
break;
}
}
@@ -378,4 +383,3 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr,
rc_calculate_inputs_outputs(ttr->compiler);
}
-
diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c
new file mode 100644
index 0000000000..b795b2e5ab
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_transfer.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Copyright 2010 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"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_context.h"
+#include "r300_transfer.h"
+#include "r300_texture.h"
+#include "r300_screen.h"
+
+#include "r300_winsys.h"
+
+#include "util/u_memory.h"
+#include "util/u_format.h"
+
+struct r300_transfer {
+ /* Parent class */
+ struct pipe_transfer transfer;
+
+ /* Offset from start of buffer. */
+ unsigned offset;
+
+ /* Detiled texture. */
+ struct r300_texture *detiled_texture;
+
+ /* Transfer and format flags. */
+ unsigned render_target_usage;
+};
+
+/* Convenience cast wrapper. */
+static INLINE struct r300_transfer*
+r300_transfer(struct pipe_transfer* transfer)
+{
+ return (struct r300_transfer*)transfer;
+}
+
+/* Copy from a tiled texture to a detiled one. */
+static void r300_copy_from_tiled_texture(struct pipe_context *ctx,
+ struct r300_transfer *r300transfer)
+{
+ struct pipe_screen *screen = ctx->screen;
+ struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer;
+ struct pipe_resource *tex = transfer->resource;
+ struct pipe_surface *src, *dst;
+
+ src = screen->get_tex_surface(screen, tex,
+ transfer->sr.face,
+ transfer->sr.level,
+ transfer->box.z,
+ PIPE_BIND_BLIT_SOURCE);
+
+ dst = screen->get_tex_surface(screen, &r300transfer->detiled_texture->b.b,
+ 0, 0, 0,
+ PIPE_BIND_BLIT_DESTINATION);
+
+ ctx->surface_copy(ctx, dst, 0, 0, src,
+ transfer->box.x, transfer->box.y,
+ transfer->box.width, transfer->box.height);
+
+ pipe_surface_reference(&src, NULL);
+ pipe_surface_reference(&dst, NULL);
+}
+
+/* Copy a detiled texture to a tiled one. */
+static void r300_copy_into_tiled_texture(struct pipe_context *ctx,
+ struct r300_transfer *r300transfer)
+{
+ struct pipe_screen *screen = ctx->screen;
+ struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer;
+ struct pipe_resource *tex = transfer->resource;
+ struct pipe_surface *src, *dst;
+
+ src = screen->get_tex_surface(screen, &r300transfer->detiled_texture->b.b,
+ 0, 0, 0,
+ PIPE_BIND_BLIT_SOURCE);
+
+ dst = screen->get_tex_surface(screen, tex,
+ transfer->sr.face,
+ transfer->sr.level,
+ transfer->box.z,
+ PIPE_BIND_BLIT_DESTINATION);
+
+ /* XXX this flush prevents the following DRM error from occuring:
+ * [drm:radeon_cs_ioctl] *ERROR* Failed to parse relocation !
+ * Reproducible with perf/copytex. */
+ ctx->flush(ctx, 0, NULL);
+
+ ctx->surface_copy(ctx, dst,
+ transfer->box.x, transfer->box.y,
+ src, 0, 0,
+ transfer->box.width, transfer->box.height);
+
+ /* XXX this flush fixes a few piglit tests (e.g. glean/pixelFormats). */
+ ctx->flush(ctx, 0, NULL);
+
+ pipe_surface_reference(&src, NULL);
+ pipe_surface_reference(&dst, NULL);
+}
+
+struct pipe_transfer*
+r300_texture_get_transfer(struct pipe_context *ctx,
+ struct pipe_resource *texture,
+ struct pipe_subresource sr,
+ unsigned usage,
+ const struct pipe_box *box)
+{
+ struct r300_texture *tex = r300_texture(texture);
+ struct r300_screen *r300screen = r300_screen(ctx->screen);
+ struct r300_transfer *trans;
+ struct pipe_resource base;
+
+ trans = CALLOC_STRUCT(r300_transfer);
+ if (trans) {
+ /* Initialize the transfer object. */
+ pipe_resource_reference(&trans->transfer.resource, texture);
+ trans->transfer.sr = sr;
+ trans->transfer.usage = usage;
+ trans->transfer.box = *box;
+
+ /* If the texture is tiled, we must create a temporary detiled texture
+ * for this transfer. */
+ if (tex->microtile || tex->macrotile) {
+ trans->render_target_usage =
+ util_format_is_depth_or_stencil(texture->format) ?
+ PIPE_BIND_DEPTH_STENCIL :
+ PIPE_BIND_RENDER_TARGET;
+
+ base.target = PIPE_TEXTURE_2D;
+ base.format = texture->format;
+ base.width0 = box->width;
+ base.height0 = box->height;
+ base.depth0 = 0;
+ base.last_level = 0;
+ base.nr_samples = 0;
+ base._usage = PIPE_USAGE_DYNAMIC;
+ base.bind = 0;
+ base.flags = R300_RESOURCE_FLAG_TRANSFER;
+
+ /* For texture reading, the temporary (detiled) texture is used as
+ * a render target when blitting from a tiled texture. */
+ if (usage & PIPE_TRANSFER_READ) {
+ base.bind |= trans->render_target_usage;
+ }
+ /* For texture writing, the temporary texture is used as a sampler
+ * when blitting into a tiled texture. */
+ if (usage & PIPE_TRANSFER_WRITE) {
+ base.bind |= PIPE_BIND_SAMPLER_VIEW;
+ }
+
+ /* Create the temporary texture. */
+ trans->detiled_texture = r300_texture(
+ ctx->screen->resource_create(ctx->screen,
+ &base));
+
+ assert(!trans->detiled_texture->microtile &&
+ !trans->detiled_texture->macrotile);
+
+ /* Set the stride.
+ *
+ * Even though we are using an internal texture for this,
+ * the transfer sr, box and usage parameters still reflect
+ * the arguments received to get_transfer. We just do the
+ * right thing internally.
+ */
+ trans->transfer.stride =
+ r300_texture_get_stride(r300screen, trans->detiled_texture, 0);
+
+ if (usage & PIPE_TRANSFER_READ) {
+ /* We cannot map a tiled texture directly because the data is
+ * in a different order, therefore we do detiling using a blit. */
+ r300_copy_from_tiled_texture(ctx, trans);
+ }
+ } else {
+ trans->transfer.stride =
+ r300_texture_get_stride(r300screen, tex, sr.level);
+ trans->offset = r300_texture_get_offset(tex, sr.level, box->z, sr.face);
+ }
+ }
+ return &trans->transfer;
+}
+
+void r300_texture_transfer_destroy(struct pipe_context *ctx,
+ struct pipe_transfer *trans)
+{
+ struct r300_transfer *r300transfer = r300_transfer(trans);
+
+ if (r300transfer->detiled_texture) {
+ if (trans->usage & PIPE_TRANSFER_WRITE) {
+ r300_copy_into_tiled_texture(ctx, r300transfer);
+ }
+
+ pipe_resource_reference(
+ (struct pipe_resource**)&r300transfer->detiled_texture, NULL);
+ }
+ pipe_resource_reference(&trans->resource, NULL);
+ FREE(trans);
+}
+
+void* r300_texture_transfer_map(struct pipe_context *ctx,
+ struct pipe_transfer *transfer)
+{
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys;
+ struct r300_transfer *r300transfer = r300_transfer(transfer);
+ struct r300_texture *tex = r300_texture(transfer->resource);
+ char *map;
+ enum pipe_format format = tex->b.b.format;
+
+ if (r300transfer->detiled_texture) {
+ /* The detiled texture is of the same size as the region being mapped
+ * (no offset needed). */
+ return rws->buffer_map(rws,
+ r300transfer->detiled_texture->buffer,
+ transfer->usage);
+ } else {
+ /* Tiling is disabled. */
+ map = rws->buffer_map(rws, tex->buffer,
+ transfer->usage);
+
+ if (!map) {
+ return NULL;
+ }
+
+ return map + r300_transfer(transfer)->offset +
+ transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
+ transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
+ }
+}
+
+void r300_texture_transfer_unmap(struct pipe_context *ctx,
+ struct pipe_transfer *transfer)
+{
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys;
+ struct r300_transfer *r300transfer = r300_transfer(transfer);
+ struct r300_texture *tex = r300_texture(transfer->resource);
+
+ if (r300transfer->detiled_texture) {
+ rws->buffer_unmap(rws, r300transfer->detiled_texture->buffer);
+ } else {
+ rws->buffer_unmap(rws, tex->buffer);
+ }
+}
+
diff --git a/src/gallium/drivers/r300/r300_transfer.h b/src/gallium/drivers/r300/r300_transfer.h
new file mode 100644
index 0000000000..d72e54e5ed
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_transfer.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Copyright 2010 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"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_TRANSFER
+#define R300_TRANSFER
+
+#include "pipe/p_screen.h"
+
+struct r300_context;
+
+struct pipe_transfer*
+r300_texture_get_transfer(struct pipe_context *ctx,
+ struct pipe_resource *texture,
+ struct pipe_subresource sr,
+ unsigned usage,
+ const struct pipe_box *box);
+
+void
+r300_texture_transfer_destroy(struct pipe_context *ctx,
+ struct pipe_transfer *trans);
+
+void*
+r300_texture_transfer_map(struct pipe_context *ctx,
+ struct pipe_transfer *transfer);
+
+void
+r300_texture_transfer_unmap(struct pipe_context *ctx,
+ struct pipe_transfer *transfer);
+
+
+#endif
diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c
index 60a04bbfed..bfab9c3b01 100644
--- a/src/gallium/drivers/r300/r300_vs.c
+++ b/src/gallium/drivers/r300/r300_vs.c
@@ -31,11 +31,10 @@
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_ureg.h"
#include "radeon_compiler.h"
-#include "util/u_math.h"
-
/* Convert info about VS output semantics into r300_shader_semantics. */
static void r300_shader_read_vs_outputs(
struct tgsi_shader_info* info,
@@ -82,102 +81,49 @@ static void r300_shader_read_vs_outputs(
case TGSI_SEMANTIC_EDGEFLAG:
assert(index == 0);
- fprintf(stderr, "r300 VP: cannot handle edgeflag output\n");
- assert(0);
+ fprintf(stderr, "r300 VP: cannot handle edgeflag output.\n");
break;
+
default:
- assert(0);
+ fprintf(stderr, "r300 VP: unknown vertex output semantic: %i.\n",
+ info->output_semantic_name[i]);
}
}
+
+ /* WPOS is a straight copy of POSITION and it's always emitted. */
+ vs_outputs->wpos = i;
}
-static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs)
+/* This function sets up:
+ * - VAP mapping, which maps VS registers to output semantics and
+ * at the same time it indicates which attributes are enabled and should
+ * be rasterized.
+ * - Stream mapping to VS outputs if TCL is not present. */
+static void r300_init_vs_output_mapping(struct r300_vertex_shader* vs)
{
struct r300_shader_semantics* vs_outputs = &vs->outputs;
- uint32_t* hwfmt = vs->hwfmt;
- int i, gen_count;
+ struct r300_vap_output_state *vap_out = &vs->vap_out;
+ int *stream_loc = vs->stream_loc_notcl;
+ int i, gen_count, tabi = 0;
boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
vs_outputs->bcolor[1] != ATTR_UNUSED;
- /* Do the actual vertex_info setup.
- *
- * vertex_info has four uints of hardware-specific data in it.
- * vinfo.hwfmt[0] is R300_VAP_VTX_STATE_CNTL
- * vinfo.hwfmt[1] is R300_VAP_VSM_VTX_ASSM
- * vinfo.hwfmt[2] is R300_VAP_OUTPUT_VTX_FMT_0
- * vinfo.hwfmt[3] is R300_VAP_OUTPUT_VTX_FMT_1 */
-
- hwfmt[0] = 0x5555; /* XXX this is classic Mesa bonghits */
+ vap_out->vap_vtx_state_cntl = 0x5555; /* XXX this is classic Mesa bonghits */
/* Position. */
if (vs_outputs->pos != ATTR_UNUSED) {
- hwfmt[1] |= R300_INPUT_CNTL_POS;
- hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
+ vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_POS;
+ vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
+
+ stream_loc[tabi++] = 0;
} else {
assert(0);
}
/* Point size. */
if (vs_outputs->psize != ATTR_UNUSED) {
- hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT;
- }
-
- /* Colors. */
- for (i = 0; i < ATTR_COLOR_COUNT; i++) {
- if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used ||
- vs_outputs->color[1] != ATTR_UNUSED) {
- hwfmt[1] |= R300_INPUT_CNTL_COLOR;
- hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i;
- }
- }
-
- /* Back-face colors. */
- if (any_bcolor_used) {
- for (i = 0; i < ATTR_COLOR_COUNT; i++) {
- hwfmt[1] |= R300_INPUT_CNTL_COLOR;
- hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i);
- }
- }
+ vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT;
- /* Texture coordinates. */
- gen_count = 0;
- for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
- if (vs_outputs->generic[i] != ATTR_UNUSED) {
- hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count);
- hwfmt[3] |= (4 << (3 * gen_count));
- gen_count++;
- }
- }
-
- /* Fog coordinates. */
- if (vs_outputs->fog != ATTR_UNUSED) {
- hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count);
- hwfmt[3] |= (4 << (3 * gen_count));
- gen_count++;
- }
-
- /* XXX magic */
- assert(gen_count <= 8);
-
- /* WPOS. */
- vs->wpos_tex_output = gen_count;
-}
-
-/* Sets up stream mapping to equivalent VS outputs if TCL is bypassed
- * or isn't present. */
-static void r300_stream_locations_notcl(
- struct r300_shader_semantics* vs_outputs,
- int* stream_loc)
-{
- int i, tabi = 0, gen_count;
- boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
- vs_outputs->bcolor[1] != ATTR_UNUSED;
-
- /* Position. */
- stream_loc[tabi++] = 0;
-
- /* Point size. */
- if (vs_outputs->psize != ATTR_UNUSED) {
stream_loc[tabi++] = 1;
}
@@ -185,6 +131,9 @@ static void r300_stream_locations_notcl(
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used ||
vs_outputs->color[1] != ATTR_UNUSED) {
+ vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR;
+ vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i;
+
stream_loc[tabi++] = 2 + i;
}
}
@@ -192,32 +141,40 @@ static void r300_stream_locations_notcl(
/* Back-face colors. */
if (any_bcolor_used) {
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
+ vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR;
+ vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i);
+
stream_loc[tabi++] = 4 + i;
}
}
/* Texture coordinates. */
gen_count = 0;
- for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
+ for (i = 0; i < ATTR_GENERIC_COUNT && gen_count < 8; i++) {
if (vs_outputs->generic[i] != ATTR_UNUSED) {
- assert(tabi < 16);
+ vap_out->vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << gen_count);
+ vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * gen_count));
+
stream_loc[tabi++] = 6 + gen_count;
gen_count++;
}
}
/* Fog coordinates. */
- if (vs_outputs->fog != ATTR_UNUSED) {
- assert(tabi < 16);
+ if (gen_count < 8 && vs_outputs->fog != ATTR_UNUSED) {
+ vap_out->vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << gen_count);
+ vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * gen_count));
+
stream_loc[tabi++] = 6 + gen_count;
gen_count++;
}
/* WPOS. */
- if (vs_outputs->wpos != ATTR_UNUSED) {
- assert(tabi < 16);
+ if (gen_count < 8) {
+ vs->wpos_tex_output = gen_count;
stream_loc[tabi++] = 6 + gen_count;
- gen_count++;
+ } else {
+ vs_outputs->wpos = ATTR_UNUSED;
}
for (; tabi < 16;) {
@@ -294,36 +251,42 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
}
}
-static void r300_insert_wpos(struct r300_vertex_program_compiler* c,
- struct r300_shader_semantics* outputs)
+static void r300_dummy_vertex_shader(
+ struct r300_context* r300,
+ struct r300_vertex_shader* shader)
{
- int i, lastOutput = 0;
+ struct pipe_shader_state state;
+ struct ureg_program *ureg;
+ struct ureg_dst dst;
+ struct ureg_src imm;
- /* Find the max output index. */
- lastOutput = MAX2(lastOutput, outputs->psize);
- for (i = 0; i < ATTR_COLOR_COUNT; i++) {
- lastOutput = MAX2(lastOutput, outputs->color[i]);
- lastOutput = MAX2(lastOutput, outputs->bcolor[i]);
- }
- for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
- lastOutput = MAX2(lastOutput, outputs->generic[i]);
- }
- lastOutput = MAX2(lastOutput, outputs->fog);
+ /* Make a simple vertex shader which outputs (0, 0, 0, 1),
+ * effectively rendering nothing. */
+ ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+ imm = ureg_imm4f(ureg, 0, 0, 0, 1);
+
+ ureg_MOV(ureg, dst, imm);
+ ureg_END(ureg);
- /* Set WPOS after the last output. */
- lastOutput++;
- rc_copy_output(&c->Base, 0, lastOutput); /* out[lastOutput] = out[0]; */
- outputs->wpos = lastOutput;
+ state.tokens = ureg_finalize(ureg);
+
+ shader->dummy = TRUE;
+ r300_translate_vertex_shader(r300, shader, state.tokens);
+
+ ureg_destroy(ureg);
}
void r300_translate_vertex_shader(struct r300_context* r300,
- struct r300_vertex_shader* vs)
+ struct r300_vertex_shader* vs,
+ const struct tgsi_token *tokens)
{
struct r300_vertex_program_compiler compiler;
struct tgsi_to_rc ttr;
- /* Initialize. */
+ tgsi_scan_shader(tokens, &vs->info);
r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
+ r300_init_vs_output_mapping(vs);
/* Setup the compiler */
rc_init(&compiler.Base);
@@ -334,7 +297,7 @@ void r300_translate_vertex_shader(struct r300_context* r300,
if (compiler.Base.Debug) {
debug_printf("r300: Initial vertex program\n");
- tgsi_dump(vs->state.tokens, 0);
+ tgsi_dump(tokens, 0);
}
/* Translate TGSI to our internal representation */
@@ -342,51 +305,68 @@ void r300_translate_vertex_shader(struct r300_context* r300,
ttr.info = &vs->info;
ttr.use_half_swizzles = FALSE;
- r300_tgsi_to_rc(&ttr, vs->state.tokens);
+ r300_tgsi_to_rc(&ttr, tokens);
+
+ compiler.RequiredOutputs =
+ ~(~0 << (vs->info.num_outputs +
+ (vs->outputs.wpos != ATTR_UNUSED ? 1 : 0)));
- compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+1));
compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
/* Insert the WPOS output. */
- r300_insert_wpos(&compiler, &vs->outputs);
-
- r300_shader_vap_output_fmt(vs);
- r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
+ if (vs->outputs.wpos != ATTR_UNUSED) {
+ rc_copy_output(&compiler.Base, 0, vs->outputs.wpos);
+ }
/* Invoke the compiler */
r3xx_compile_vertex_program(&compiler);
if (compiler.Base.Error) {
/* XXX We should fallback using Draw. */
- fprintf(stderr, "r300 VP: Compiler error\n");
- abort();
+ fprintf(stderr, "r300 VP: Compiler error:\n%sUsing a dummy shader"
+ " instead.\n", compiler.Base.ErrorMsg);
+
+ if (vs->dummy) {
+ fprintf(stderr, "r300 VP: Cannot compile the dummy shader! "
+ "Giving up...\n");
+ abort();
+ }
+
+ rc_destroy(&compiler.Base);
+ r300_dummy_vertex_shader(r300, vs);
+ return;
}
+ /* Initialize numbers of constants for each type. */
+ vs->externals_count = ttr.immediate_offset;
+ vs->immediates_count = vs->code.constants.Count - vs->externals_count;
+
/* And, finally... */
rc_destroy(&compiler.Base);
- vs->translated = TRUE;
}
boolean r300_vertex_shader_setup_wpos(struct r300_context* r300)
{
struct r300_vertex_shader* vs = r300->vs_state.state;
+ struct r300_vap_output_state *vap_out = &vs->vap_out;
int tex_output = vs->wpos_tex_output;
uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output;
- uint32_t* hwfmt = vs->hwfmt;
- if (r300->fs->inputs.wpos != ATTR_UNUSED) {
- /* Enable WPOS in VAP. */
- if (!(hwfmt[1] & tex_fmt)) {
- hwfmt[1] |= tex_fmt;
- hwfmt[3] |= (4 << (3 * tex_output));
+ if (vs->outputs.wpos == ATTR_UNUSED) {
+ return FALSE;
+ }
- assert(tex_output < 8);
+ if (r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) {
+ /* Enable WPOS in VAP. */
+ if (!(vap_out->vap_vsm_vtx_assm & tex_fmt)) {
+ vap_out->vap_vsm_vtx_assm |= tex_fmt;
+ vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * tex_output));
return TRUE;
}
} else {
/* Disable WPOS in VAP. */
- if (hwfmt[1] & tex_fmt) {
- hwfmt[1] &= ~tex_fmt;
- hwfmt[3] &= ~(4 << (3 * tex_output));
+ if (vap_out->vap_vsm_vtx_assm & tex_fmt) {
+ vap_out->vap_vsm_vtx_assm &= ~tex_fmt;
+ vap_out->vap_out_vtx_fmt[1] &= ~(4 << (3 * tex_output));
return TRUE;
}
}
diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h
index 18cfeee3cd..56bcc3b70b 100644
--- a/src/gallium/drivers/r300/r300_vs.h
+++ b/src/gallium/drivers/r300/r300_vs.h
@@ -28,6 +28,7 @@
#include "tgsi/tgsi_scan.h"
#include "radeon_code.h"
+#include "r300_context.h"
#include "r300_shader_semantics.h"
struct r300_context;
@@ -38,7 +39,15 @@ struct r300_vertex_shader {
struct tgsi_shader_info info;
struct r300_shader_semantics outputs;
- uint hwfmt[4];
+ struct r300_vap_output_state vap_out;
+
+ /* Whether the shader was replaced by a dummy one due to a shader
+ * compilation failure. */
+ boolean dummy;
+
+ /* Numbers of constants for each type. */
+ unsigned externals_count;
+ unsigned immediates_count;
/* Stream locations for SWTCL or if TCL is bypassed. */
int stream_loc_notcl[16];
@@ -46,15 +55,17 @@ struct r300_vertex_shader {
/* Output stream location for WPOS. */
int wpos_tex_output;
- /* Has this shader been translated yet? */
- boolean translated;
-
+ /* HWTCL-specific. */
/* Machine code (if translated) */
struct r300_vertex_program_code code;
+
+ /* SWTCL-specific. */
+ void *draw_vs;
};
void r300_translate_vertex_shader(struct r300_context* r300,
- struct r300_vertex_shader* vs);
+ struct r300_vertex_shader* vs,
+ const struct tgsi_token *tokens);
/* Return TRUE if VAP (hwfmt) needs to be re-emitted. */
boolean r300_vertex_shader_setup_wpos(struct r300_context* r300);
diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h
index 40fb8a95ca..2bd40176d1 100644
--- a/src/gallium/drivers/r300/r300_winsys.h
+++ b/src/gallium/drivers/r300/r300_winsys.h
@@ -23,10 +23,6 @@
#ifndef R300_WINSYS_H
#define R300_WINSYS_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* The public interface header for the r300 pipe driver.
* Any winsys hosting this pipe needs to implement r300_winsys and then
* call r300_create_screen to start things. */
@@ -34,19 +30,149 @@ extern "C" {
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
-struct radeon_winsys;
+#include "r300_defines.h"
-/* Creates a new r300 screen. */
-struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys);
+struct r300_winsys_buffer;
+
+enum r300_value_id {
+ R300_VID_PCI_ID,
+ R300_VID_GB_PIPES,
+ R300_VID_Z_PIPES,
+ R300_VID_SQUARE_TILING_SUPPORT,
+ R300_VID_TEX3D_MIP_BUG,
+};
+
+enum r300_reference_domain { /* bitfield */
+ R300_REF_CS = 1,
+ R300_REF_HW = 2
+};
+
+struct r300_winsys_screen {
+ void (*destroy)(struct r300_winsys_screen *ws);
+
+ /**
+ * Buffer management. Buffer attributes are mostly fixed over its lifetime.
+ *
+ * Remember that gallium gets to choose the interface it needs, and the
+ * window systems must then implement that interface (rather than the
+ * other way around...).
+ *
+ * usage is a bitmask of R300_WINSYS_BUFFER_USAGE_PIXEL/VERTEX/INDEX/CONSTANT. This
+ * usage argument is only an optimization hint, not a guarantee, therefore
+ * proper behavior must be observed in all circumstances.
+ *
+ * alignment indicates the client's alignment requirements, eg for
+ * SSE instructions.
+ */
+ struct r300_winsys_buffer *(*buffer_create)(struct r300_winsys_screen *ws,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size);
+
+ /**
+ * Map the entire data store of a buffer object into the client's address.
+ * flags is bitmask of R300_WINSYS_BUFFER_USAGE_CPU_READ/WRITE flags.
+ */
+ void *(*buffer_map)( struct r300_winsys_screen *ws,
+ struct r300_winsys_buffer *buf,
+ unsigned usage);
+
+ void (*buffer_unmap)( struct r300_winsys_screen *ws,
+ struct r300_winsys_buffer *buf );
+
+ void (*buffer_destroy)( struct r300_winsys_buffer *buf );
+
+
+ void (*buffer_reference)(struct r300_winsys_screen *rws,
+ struct r300_winsys_buffer **pdst,
+ struct r300_winsys_buffer *src);
+
+ boolean (*buffer_references)(struct r300_winsys_buffer *a,
+ struct r300_winsys_buffer *b);
+
+ void (*buffer_flush_range)(struct r300_winsys_screen *rws,
+ struct r300_winsys_buffer *buf,
+ unsigned offset,
+ unsigned length);
+
+ /* Add a pipe_resource to the list of buffer objects to validate. */
+ boolean (*add_buffer)(struct r300_winsys_screen *winsys,
+ struct r300_winsys_buffer *buf,
+ uint32_t rd,
+ uint32_t wd);
+
+
+ /* Revalidate all currently setup pipe_buffers.
+ * Returns TRUE if a flush is required. */
+ boolean (*validate)(struct r300_winsys_screen* winsys);
+ /* Check to see if there's room for commands. */
+ boolean (*check_cs)(struct r300_winsys_screen* winsys, int size);
-boolean r300_get_texture_buffer(struct pipe_screen* screen,
- struct pipe_texture* texture,
- struct pipe_buffer** buffer,
- unsigned* stride);
+ /* Start a command emit. */
+ void (*begin_cs)(struct r300_winsys_screen* winsys,
+ int size,
+ const char* file,
+ const char* function,
+ int line);
-#ifdef __cplusplus
-}
-#endif
+ /* Write a dword to the command buffer. */
+ void (*write_cs_dword)(struct r300_winsys_screen* winsys, uint32_t dword);
+
+ /* Write a relocated dword to the command buffer. */
+ void (*write_cs_reloc)(struct r300_winsys_screen *winsys,
+ struct r300_winsys_buffer *buf,
+ uint32_t rd,
+ uint32_t wd,
+ uint32_t flags);
+
+ /* Finish a command emit. */
+ void (*end_cs)(struct r300_winsys_screen* winsys,
+ const char* file,
+ const char* function,
+ int line);
+
+ /* Flush the CS. */
+ void (*flush_cs)(struct r300_winsys_screen* winsys);
+
+ /* winsys flush - callback from winsys when flush required */
+ void (*set_flush_cb)(struct r300_winsys_screen *winsys,
+ void (*flush_cb)(void *), void *data);
+
+ void (*reset_bos)(struct r300_winsys_screen *winsys);
+
+ void (*buffer_get_tiling)(struct r300_winsys_screen *winsys,
+ struct r300_winsys_buffer *buffer,
+ enum r300_buffer_tiling *microtiled,
+ enum r300_buffer_tiling *macrotiled);
+
+ void (*buffer_set_tiling)(struct r300_winsys_screen *winsys,
+ struct r300_winsys_buffer *buffer,
+ uint32_t pitch,
+ enum r300_buffer_tiling microtiled,
+ enum r300_buffer_tiling macrotiled);
+
+ uint32_t (*get_value)(struct r300_winsys_screen *winsys,
+ enum r300_value_id vid);
+
+ struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *winsys,
+ struct pipe_screen *screen,
+ struct winsys_handle *whandle,
+ unsigned *stride);
+ boolean (*buffer_get_handle)(struct r300_winsys_screen *winsys,
+ struct r300_winsys_buffer *buffer,
+ unsigned stride,
+ struct winsys_handle *whandle);
+
+ boolean (*is_buffer_referenced)(struct r300_winsys_screen *winsys,
+ struct r300_winsys_buffer *buffer,
+ enum r300_reference_domain domain);
+};
+
+struct r300_winsys_screen *
+r300_winsys_screen(struct pipe_screen *screen);
+
+/* Creates a new r300 screen. */
+struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws);
#endif /* R300_WINSYS_H */