summaryrefslogtreecommitdiffstats
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/Makefile1
-rw-r--r--src/gallium/drivers/r300/r300_context.c38
-rw-r--r--src/gallium/drivers/r300/r300_context.h9
-rw-r--r--src/gallium/drivers/r300/r300_cs.h22
-rw-r--r--src/gallium/drivers/r300/r300_debug.c1
-rw-r--r--src/gallium/drivers/r300/r300_emit.c75
-rw-r--r--src/gallium/drivers/r300/r300_emit.h3
-rw-r--r--src/gallium/drivers/r300/r300_reg.h4
-rw-r--r--src/gallium/drivers/r300/r300_render.c47
-rw-r--r--src/gallium/drivers/r300/r300_screen.c31
-rw-r--r--src/gallium/drivers/r300/r300_screen.h10
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.c314
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.h99
-rw-r--r--src/gallium/drivers/r300/r300_state.c39
-rw-r--r--src/gallium/drivers/r300/r300_state_inlines.h12
-rw-r--r--src/gallium/drivers/r300/r300_texture.c52
-rw-r--r--src/gallium/drivers/r300/r300_texture.h4
-rw-r--r--src/gallium/drivers/r300/r300_transfer.c12
-rw-r--r--src/gallium/drivers/r300/r300_vs.c2
-rw-r--r--src/gallium/drivers/r300/r300_winsys.h146
20 files changed, 803 insertions, 118 deletions
diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile
index 61b54af4ddf..a6529b20604 100644
--- a/src/gallium/drivers/r300/Makefile
+++ b/src/gallium/drivers/r300/Makefile
@@ -14,6 +14,7 @@ C_SOURCES = \
r300_query.c \
r300_render.c \
r300_screen.c \
+ r300_screen_buffer.c \
r300_state.c \
r300_state_derived.c \
r300_state_invariant.c \
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index 8606c0004e5..d994a46ccfe 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"
@@ -55,6 +56,9 @@ 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);
@@ -72,8 +76,7 @@ r300_is_texture_referenced(struct pipe_context *pipe,
struct pipe_texture *texture,
unsigned face, unsigned level)
{
- return pipe->is_buffer_referenced(pipe,
- ((struct r300_texture *)texture)->buffer);
+ return 0;
}
static unsigned int
@@ -157,16 +160,14 @@ 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;
- r300screen->ctx = (struct pipe_context*)r300;
-
- r300->winsys = radeon_winsys;
+ r300->rws = rws;
- r300->context.winsys = (struct pipe_winsys*)radeon_winsys;
+ r300->context.winsys = (struct pipe_winsys*)rws;
r300->context.screen = screen;
r300->context.priv = priv;
@@ -212,16 +213,33 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300_init_transfer_functions(r300);
- /* r300_init_surface_functions(r300); */
-
r300_init_state_functions(r300);
r300->invariant_state.dirty = TRUE;
- r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300);
+ 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(screen,
+ 32 * 1024, 16,
+ PIPE_BUFFER_USAGE_INDEX);
+
+ if (r300->upload_ib == NULL)
+ goto no_upload_ib;
+
+ r300->upload_vb = u_upload_create(screen,
+ 128 * 1024, 16,
+ PIPE_BUFFER_USAGE_VERTEX);
+ 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 7b86669888b..2763103fda1 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -32,6 +32,7 @@
#include "r300_screen.h"
+struct u_upload_mgr;
struct r300_context;
struct r300_fragment_shader;
@@ -268,7 +269,7 @@ struct r300_texture {
boolean is_npot;
/* 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;
@@ -302,7 +303,7 @@ struct r300_context {
struct pipe_context context;
/* The interface to the windowing system, etc. */
- struct radeon_winsys* winsys;
+ struct r300_winsys_screen *rws;
/* Draw module. Used mostly for SW TCL. */
struct draw_context* draw;
/* Accelerated blit support. */
@@ -369,6 +370,7 @@ struct r300_context {
int vertex_buffer_max_index;
/* Vertex elements for Gallium. */
struct r300_vertex_element_state *velems;
+ bool any_user_vbs;
/* Vertex info for Draw. */
struct vertex_info vertex_info;
@@ -389,6 +391,9 @@ struct r300_context {
uint32_t zbuffer_bpp;
/* Whether scissor is enabled. */
boolean scissor_enabled;
+ /* upload managers */
+ struct u_upload_mgr *upload_vb;
+ struct u_upload_mgr *upload_ib;
};
/* Convenience cast wrapper. */
diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h
index 151f72b0fe4..ad07efbffdb 100644
--- a/src/gallium/drivers/r300/r300_cs.h
+++ b/src/gallium/drivers/r300/r300_cs.h
@@ -51,7 +51,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 +105,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_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \
+
+#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_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 b881730848a..d6177577c8d 100644
--- a/src/gallium/drivers/r300/r300_debug.c
+++ b/src/gallium/drivers/r300/r300_debug.c
@@ -37,6 +37,7 @@ static struct debug_option debug_options[] = {
{ "draw", DBG_DRAW, "Draw and emit" },
{ "tex", DBG_TEX, "Textures" },
{ "fall", DBG_FALL, "Fallbacks" },
+ { "anisohq", DBG_ANISOHQ, "High quality anisotropic filtering (for benchmarking purposes only!)" },
{ "all", ~0, "Convenience option that enables all debug flags" },
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index fc8a8a27738..0a3f0f45c03 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -32,6 +32,8 @@
#include "r300_emit.h"
#include "r300_fs.h"
#include "r300_screen.h"
+#include "r300_screen_buffer.h"
+#include "r300_state_inlines.h"
#include "r300_vs.h"
void r300_emit_blend_state(struct r300_context* r300,
@@ -415,10 +417,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
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);
@@ -434,12 +436,12 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
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);
}
@@ -448,7 +450,7 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
END_CS;
}
-static void r300_emit_query_start(struct r300_context *r300)
+void r300_emit_query_start(struct r300_context *r300)
{
struct r300_capabilities *caps = r300_screen(r300->context.screen)->caps;
struct r300_query *query = r300->query_current;
@@ -491,13 +493,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,13 +507,13 @@ 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:
@@ -533,7 +535,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,10 +548,10 @@ 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;
}
@@ -747,7 +749,7 @@ void r300_emit_textures_state(struct r300_context *r300,
OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format[2]);
OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1);
- OUT_CS_RELOC(allstate->textures[i]->buffer, texstate->tile_config,
+ OUT_CS_TEX_RELOC(allstate->textures[i], texstate->tile_config,
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0);
}
}
@@ -788,8 +790,8 @@ 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;
}
@@ -814,7 +816,7 @@ void r300_emit_vertex_buffer(struct r300_context* r300)
OUT_CS(r300->vertex_info.size |
(r300->vertex_info.size << 8));
OUT_CS(r300->vbo_offset);
- OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ OUT_CS_BUF_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0);
END_CS;
}
@@ -1009,16 +1011,22 @@ void r300_emit_buffer_validate(struct r300_context *r300,
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;
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;
}
@@ -1027,8 +1035,8 @@ validate:
if (fb->zsbuf) {
tex = (struct 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;
}
@@ -1038,24 +1046,24 @@ validate:
if (!r300->fragment_sampler_views[i])
continue;
tex = (struct r300_texture *)r300->fragment_sampler_views[i]->texture;
- if (!r300->winsys->add_buffer(r300->winsys, tex->buffer,
- RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) {
+ 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_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;
}
@@ -1065,23 +1073,22 @@ validate:
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. */
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 449e640a884..7db2fc6a1a1 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -57,8 +57,7 @@ void r500_emit_fs_constant_buffer(struct r300_context* r300,
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);
void r300_emit_query_end(struct r300_context* r300);
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index c67cc868713..1c2b2528877 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
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index ccf39876a59..47100c83b0b 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -30,10 +30,12 @@
#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"
@@ -123,7 +125,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,9 +133,37 @@ 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 > 4) {
+ 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,
+ vbuf->buffer)) {
+ /* 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,
@@ -316,8 +346,8 @@ 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;
}
@@ -384,12 +414,16 @@ void r300_draw_range_elements(struct pipe_context* pipe,
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);
@@ -412,7 +446,7 @@ void r300_draw_range_elements(struct pipe_context* pipe,
}
if (indexBuffer != orgIndexBuffer) {
- pipe->screen->buffer_destroy(indexBuffer);
+ pipe_buffer_reference( &indexBuffer, NULL );
}
}
@@ -476,6 +510,7 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
}
} while (count);
}
+ u_upload_flush(r300->upload_vb);
}
}
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index 64d1909a382..3e31688f8e8 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -23,13 +23,13 @@
#include "util/u_format.h"
#include "util/u_memory.h"
-#include "util/u_simple_screen.h"
#include "r300_context.h"
#include "r300_texture.h"
#include "radeon_winsys.h"
-#include "r300_winsys.h"
+
+#include "r300_screen_buffer.h"
/* Return the identifier behind whom the brave coders responsible for this
* amalgamation of code, sweat, and duct tape, routinely obscure their names.
@@ -254,15 +254,19 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
static void r300_destroy_screen(struct pipe_screen* pscreen)
{
struct r300_screen* r300screen = r300_screen(pscreen);
+ struct r300_winsys_screen *rws = r300_winsys_screen(pscreen);
+
+ if (rws)
+ rws->destroy(rws);
FREE(r300screen->caps);
FREE(r300screen);
}
-struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys)
+struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws)
{
- struct r300_screen* r300screen = CALLOC_STRUCT(r300_screen);
- struct r300_capabilities* caps = CALLOC_STRUCT(r300_capabilities);
+ struct r300_screen *r300screen = CALLOC_STRUCT(r300_screen);
+ struct r300_capabilities *caps = CALLOC_STRUCT(r300_capabilities);
if (!r300screen || !caps) {
FREE(r300screen);
@@ -270,16 +274,16 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys)
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;
+ caps->pci_id = rws->get_value(rws, R300_VID_PCI_ID);
+ caps->num_frag_pipes = rws->get_value(rws, R300_VID_GB_PIPES);
+ caps->num_z_pipes = rws->get_value(rws, R300_VID_Z_PIPES);
r300_init_debug(r300screen);
r300_parse_chipset(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;
@@ -289,8 +293,13 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys)
r300screen->screen.context_create = r300_create_context;
r300_init_screen_texture_functions(&r300screen->screen);
- u_simple_screen_init(&r300screen->screen);
+ r300_screen_init_buffer_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 484bde6a6be..1ccc0bfb7a5 100644
--- a/src/gallium/drivers/r300/r300_screen.h
+++ b/src/gallium/drivers/r300/r300_screen.h
@@ -36,11 +36,7 @@ struct r300_screen {
/* Parent class */
struct pipe_screen screen;
- struct radeon_winsys* radeon_winsys;
-
- /* XXX This hack will be removed once texture transfers become part of
- * pipe_context. */
- struct pipe_context* ctx;
+ struct r300_winsys_screen *rws;
/* Chipset capabilities */
struct r300_capabilities* caps;
@@ -55,9 +51,6 @@ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) {
return (struct r300_screen*)screen;
}
-/* Creates a new r300 screen. */
-struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys);
-
/* Debug functionality. */
/**
@@ -77,6 +70,7 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys);
#define DBG_DRAW 0x0000010
#define DBG_TEX 0x0000020
#define DBG_FALL 0x0000040
+#define DBG_ANISOHQ 0x0000080
/*@}*/
static INLINE boolean SCREEN_DBG_ON(struct r300_screen * screen, unsigned flags)
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 00000000000..b97d0d76a4a
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_screen_buffer.c
@@ -0,0 +1,314 @@
+/*
+ * 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_screen_buffer.h"
+
+#include "r300_winsys.h"
+
+boolean r300_buffer_is_referenced(struct r300_context *r300,
+ struct pipe_buffer *buf)
+{
+ struct r300_buffer *rbuf = r300_buffer(buf);
+ if (r300_buffer_is_user_buffer(buf))
+ return FALSE;
+
+ return r300->rws->is_buffer_referenced(r300->rws, rbuf->buf);
+
+}
+int r300_upload_index_buffer(struct r300_context *r300,
+ struct pipe_buffer **index_buffer,
+ unsigned index_size,
+ unsigned start,
+ unsigned count)
+{
+ struct pipe_buffer *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_buffer_reference(&upload_buffer, NULL);
+ return ret;
+}
+
+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_buffer *upload_buffer = NULL;
+ unsigned offset = 0; /*r300->vertex_buffer[i].buffer_offset * 4;*/
+ unsigned size = r300->vertex_buffer[i].buffer->size;
+ 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_buffer_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 struct pipe_buffer *r300_buffer_create(struct pipe_screen *screen,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct r300_screen *r300screen = r300_screen(screen);
+ struct r300_buffer *rbuf;
+
+ rbuf = CALLOC_STRUCT(r300_buffer);
+ if (!rbuf)
+ goto error1;
+
+ rbuf->magic = R300_BUFFER_MAGIC;
+
+ pipe_reference_init(&rbuf->base.reference, 1);
+ rbuf->base.screen = screen;
+ rbuf->base.alignment = alignment;
+ rbuf->base.usage = usage;
+ rbuf->base.size = size;
+
+ rbuf->buf = r300_winsys_buffer_create(r300screen,
+ alignment,
+ usage,
+ size);
+
+ if (!rbuf->buf)
+ goto error2;
+
+ return &rbuf->base;
+error2:
+ FREE(rbuf);
+error1:
+ return NULL;
+}
+
+
+static struct pipe_buffer *r300_user_buffer_create(struct pipe_screen *screen,
+ void *ptr,
+ unsigned bytes)
+{
+ struct r300_buffer *rbuf;
+
+ rbuf = CALLOC_STRUCT(r300_buffer);
+ if (!rbuf)
+ goto no_rbuf;
+
+ rbuf->magic = R300_BUFFER_MAGIC;
+
+ pipe_reference_init(&rbuf->base.reference, 1);
+ rbuf->base.screen = screen;
+ rbuf->base.alignment = 1;
+ rbuf->base.usage = 0;
+ rbuf->base.size = bytes;
+
+ rbuf->user_buffer = ptr;
+ return &rbuf->base;
+
+no_rbuf:
+ return NULL;
+}
+
+static void r300_buffer_destroy(struct pipe_buffer *buf)
+{
+ struct r300_screen *r300screen = r300_screen(buf->screen);
+ struct r300_buffer *rbuf = r300_buffer(buf);
+
+ r300_winsys_buffer_destroy(r300screen, rbuf);
+ FREE(rbuf);
+}
+
+static void *
+r300_buffer_map_range(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset, unsigned length,
+ unsigned usage )
+{
+ struct r300_screen *r300screen = r300_screen(screen);
+ struct r300_winsys_screen *rws = r300screen->rws;
+ struct r300_buffer *rbuf = r300_buffer(buf);
+ void *map;
+ int flush = 0;
+ int i;
+
+ if (rbuf->user_buffer)
+ return rbuf->user_buffer;
+
+ if (rbuf->base.usage & PIPE_BUFFER_USAGE_CONSTANT)
+ goto just_map;
+
+ /* check if the mapping is to a range we already flushed */
+ if (usage & PIPE_BUFFER_USAGE_DISCARD) {
+ for (i = 0; i < rbuf->num_ranges; i++) {
+
+ if ((offset >= rbuf->ranges[i].start) &&
+ (offset < rbuf->ranges[i].end))
+ flush = 1;
+
+ if (flush) {
+ /* unreference this hw buffer and allocate a new one */
+ rws->buffer_reference(rws, &rbuf->buf, NULL);
+
+ rbuf->num_ranges = 0;
+ rbuf->map = NULL;
+ rbuf->buf = r300_winsys_buffer_create(r300screen,
+ rbuf->base.alignment,
+ rbuf->base.usage,
+ rbuf->base.size);
+ break;
+ }
+ }
+ }
+just_map:
+ map = rws->buffer_map(rws, rbuf->buf, usage | R300_USAGE_FLAG_DONT_SYNC);
+
+ return map;
+}
+
+static void
+r300_buffer_flush_mapped_range( struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset,
+ unsigned length )
+{
+ struct r300_buffer *rbuf = r300_buffer(buf);
+ int i;
+
+ if (rbuf->user_buffer)
+ return;
+
+ if (rbuf->base.usage & PIPE_BUFFER_USAGE_CONSTANT)
+ 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+length)) {
+ 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_map(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned usage)
+{
+ struct r300_screen *r300screen = r300_screen(screen);
+ struct r300_winsys_screen *rws = r300screen->rws;
+ struct r300_buffer *rbuf = r300_buffer(buf);
+ void *map;
+
+ if (rbuf->user_buffer)
+ return rbuf->user_buffer;
+
+ map = rws->buffer_map(rws, rbuf->buf, usage);
+
+ return map;
+}
+
+static void
+r300_buffer_unmap(struct pipe_screen *screen,
+ struct pipe_buffer *buf)
+{
+ struct r300_screen *r300screen = r300_screen(screen);
+ struct r300_winsys_screen *rws = r300screen->rws;
+ struct r300_buffer *rbuf = r300_buffer(buf);
+
+ if (rbuf->buf) {
+ rws->buffer_unmap(rws, rbuf->buf);
+ }
+}
+
+void r300_screen_init_buffer_functions(struct r300_screen *r300screen)
+{
+ r300screen->screen.buffer_create = r300_buffer_create;
+ r300screen->screen.user_buffer_create = r300_user_buffer_create;
+ r300screen->screen.buffer_map = r300_buffer_map;
+ r300screen->screen.buffer_map_range = r300_buffer_map_range;
+ r300screen->screen.buffer_flush_mapped_range = r300_buffer_flush_mapped_range;
+ r300screen->screen.buffer_unmap = r300_buffer_unmap;
+ r300screen->screen.buffer_destroy = r300_buffer_destroy;
+}
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 00000000000..0cf349c25cd
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_screen_buffer.h
@@ -0,0 +1,99 @@
+#ifndef R300_SCREEN_BUFFER_H
+#define R300_SCREEN_BUFFER_H
+#include <stdio.h>
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+#include "r300_screen.h"
+
+#include "r300_winsys.h"
+#include "r300_context.h"
+
+#define R300_BUFFER_MAGIC 0xabcd1234
+
+struct r300_buffer_range {
+ uint32_t start;
+ uint32_t end;
+};
+#define R300_BUFFER_MAX_RANGES 32
+
+struct r300_buffer
+{
+ struct pipe_buffer base;
+
+ uint32_t magic;
+
+ struct r300_winsys_buffer *buf;
+
+ void *user_buffer;
+ struct r300_buffer_range ranges[R300_BUFFER_MAX_RANGES];
+ unsigned num_ranges;
+
+ void *map;
+};
+
+static INLINE struct r300_buffer *
+r300_buffer(struct pipe_buffer *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_buffer *buffer)
+{
+ return r300_buffer(buffer)->user_buffer ? true : false;
+}
+
+static INLINE boolean r300_add_buffer(struct r300_winsys_screen *rws,
+ struct pipe_buffer *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);
+}
+
+void r300_screen_init_buffer_functions(struct r300_screen *r300screen);
+
+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);
+}
+
+int r300_upload_user_buffers(struct r300_context *r300);
+
+int r300_upload_index_buffer(struct r300_context *r300,
+ struct pipe_buffer **index_buffer,
+ unsigned index_size,
+ unsigned start,
+ unsigned count);
+
+boolean r300_buffer_is_referenced(struct r300_context *r300,
+ struct pipe_buffer *buf);
+#endif
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index d4b7376f126..71ac89715cc 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -34,6 +34,7 @@
#include "r300_context.h"
#include "r300_reg.h"
#include "r300_screen.h"
+#include "r300_screen_buffer.h"
#include "r300_state_inlines.h"
#include "r300_fs.h"
#include "r300_vs.h"
@@ -525,7 +526,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
tex = (struct 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);
@@ -537,7 +538,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
tex = (struct 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);
@@ -549,7 +550,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
tex = (struct 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);
@@ -558,7 +559,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
tex = (struct 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);
@@ -849,6 +850,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(pipe->screen)->caps->is_r500;
int lod_bias;
union util_color uc;
@@ -864,6 +866,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);
@@ -873,7 +877,13 @@ 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;
@@ -1061,17 +1071,30 @@ 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 = (1 << 24) - 1;
+ int i;
+ unsigned 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, count * sizeof(buffers[0])) == 0)
+ return;
for (i = 0; i < count; i++) {
+ pipe_buffer_reference(&r300->vertex_buffer[i].buffer, buffers[i].buffer);
+ if (r300_buffer_is_user_buffer(buffers[i].buffer))
+ any_user_buffer = true;
max_index = MIN2(buffers[i].max_index, max_index);
}
+ for ( ; i < r300->vertex_buffer_count; i++)
+ pipe_buffer_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);
diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h
index a32924ed0a3..8485d4f8f94 100644
--- a/src/gallium/drivers/r300/r300_state_inlines.h
+++ b/src/gallium/drivers/r300/r300_state_inlines.h
@@ -327,6 +327,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)
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 04124afd4dc..7c7656068bb 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -773,7 +773,7 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen,
{
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;
@@ -790,13 +790,13 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen,
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);
+ tex->buffer = rws->buffer_create(rws, 2048,
+ PIPE_BUFFER_USAGE_PIXEL,
+ tex->size);
+ rws->buffer_set_tiling(rws, tex->buffer,
+ tex->pitch[0],
+ tex->microtile != R300_BUFFER_LINEAR,
+ tex->macrotile != R300_BUFFER_LINEAR);
if (!tex->buffer) {
FREE(tex);
@@ -809,9 +809,9 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen,
static void r300_texture_destroy(struct pipe_texture* texture)
{
struct r300_texture* tex = (struct r300_texture*)texture;
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys;
- pipe_buffer_reference(&tex->buffer, NULL);
-
+ rws->buffer_reference(rws, &tex->buffer, NULL);
FREE(tex);
}
@@ -857,9 +857,9 @@ static struct pipe_texture*
const struct pipe_texture* base,
struct winsys_handle *whandle)
{
- struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys;
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys;
struct r300_screen* rscreen = r300_screen(screen);
- struct pipe_buffer *buffer;
+ struct r300_winsys_buffer *buffer;
struct r300_texture* tex;
unsigned stride;
@@ -870,7 +870,7 @@ static struct pipe_texture*
return NULL;
}
- buffer = winsys->buffer_from_handle(winsys, screen, whandle, &stride);
+ buffer = rws->buffer_from_handle(rws, screen, whandle, &stride);
if (!buffer) {
return NULL;
}
@@ -901,7 +901,7 @@ static boolean
struct pipe_texture *texture,
struct winsys_handle *whandle)
{
- struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys;
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
struct r300_texture* tex = (struct r300_texture*)texture;
unsigned stride;
@@ -911,7 +911,7 @@ static boolean
stride = r300_texture_get_stride(r300_screen(screen), tex, 0);
- winsys->buffer_get_handle(winsys, tex->buffer, stride, whandle);
+ rws->buffer_get_handle(rws, tex->buffer, stride, whandle);
return TRUE;
}
@@ -977,3 +977,25 @@ void r300_init_screen_texture_functions(struct pipe_screen* screen)
screen->video_surface_destroy= r300_video_surface_destroy;
}
+boolean r300_get_texture_buffer(struct pipe_screen* screen,
+ struct pipe_texture* texture,
+ struct r300_winsys_buffer** buffer,
+ unsigned* stride)
+{
+ struct r300_texture* tex = (struct r300_texture*)texture;
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
+ struct r300_winsys_buffer *buf;
+
+ if (!tex) {
+ return FALSE;
+ }
+
+ rws->buffer_reference(rws, &buf, tex->buffer);
+
+ if (stride) {
+ *stride = r300_texture_get_stride(r300_screen(screen), tex, 0);
+ }
+
+ *buffer = buf;
+ return TRUE;
+}
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index 138b62784e6..60c7fa83420 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -63,8 +63,8 @@ r300_video_surface(struct pipe_video_surface *pvs)
/* Used internally for texture_is_referenced()
*/
boolean r300_get_texture_buffer(struct pipe_screen* screen,
- struct pipe_texture* texture,
- struct pipe_buffer** buffer,
+ struct pipe_texture *texture,
+ struct r300_winsys_buffer** buffer,
unsigned* stride);
#endif /* R300_TEXTURE_H */
diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c
index 495e3dee767..987a040698f 100644
--- a/src/gallium/drivers/r300/r300_transfer.c
+++ b/src/gallium/drivers/r300/r300_transfer.c
@@ -26,6 +26,8 @@
#include "r300_texture.h"
#include "r300_screen.h"
+#include "r300_winsys.h"
+
#include "util/u_memory.h"
#include "util/u_format.h"
@@ -225,6 +227,7 @@ static void r300_tex_transfer_destroy(struct pipe_context *ctx,
static void* r300_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 = (struct r300_texture*)transfer->texture;
char *map;
@@ -233,12 +236,12 @@ static void* r300_transfer_map(struct pipe_context *ctx,
if (r300transfer->detiled_texture) {
/* The detiled texture is of the same size as the region being mapped
* (no offset needed). */
- return pipe_buffer_map(ctx->screen,
+ return rws->buffer_map(rws,
r300transfer->detiled_texture->buffer,
pipe_transfer_buffer_flags(transfer));
} else {
/* Tiling is disabled. */
- map = pipe_buffer_map(ctx->screen, tex->buffer,
+ map = rws->buffer_map(rws, tex->buffer,
pipe_transfer_buffer_flags(transfer));
if (!map) {
@@ -254,13 +257,14 @@ static void* r300_transfer_map(struct pipe_context *ctx,
static void r300_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 = (struct r300_texture*)transfer->texture;
if (r300transfer->detiled_texture) {
- pipe_buffer_unmap(ctx->screen, r300transfer->detiled_texture->buffer);
+ rws->buffer_unmap(rws, r300transfer->detiled_texture->buffer);
} else {
- pipe_buffer_unmap(ctx->screen, tex->buffer);
+ rws->buffer_unmap(rws, tex->buffer);
}
}
diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c
index 379939ac750..bd6b95dccba 100644
--- a/src/gallium/drivers/r300/r300_vs.c
+++ b/src/gallium/drivers/r300/r300_vs.c
@@ -34,8 +34,6 @@
#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,
diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h
index ddf2b790039..e5183a8239c 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,14 +30,146 @@ extern "C" {
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
-struct radeon_winsys;
+struct r300_winsys_screen;
/* Creates a new r300 screen. */
-struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys);
+struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws);
+
+struct r300_winsys_buffer;
+
+
+boolean r300_get_texture_buffer(struct pipe_screen* screen,
+ struct pipe_texture* texture,
+ struct r300_winsys_buffer** buffer,
+ unsigned *stride);
+
+enum r300_value_id {
+ R300_VID_PCI_ID,
+ R300_VID_GB_PIPES,
+ R300_VID_Z_PIPES,
+};
+
+#define R300_USAGE_FLAG_DONT_SYNC (1 << 17)
+
+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_buffer 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);
+
+ /* Start a command emit. */
+ void (*begin_cs)(struct r300_winsys_screen* winsys,
+ int size,
+ const char* file,
+ const char* function,
+ int line);
+
+ /* 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_set_tiling)(struct r300_winsys_screen *winsys,
+ struct r300_winsys_buffer *buffer,
+ uint32_t pitch,
+ boolean microtiled,
+ boolean 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);
+
+};
-#ifdef __cplusplus
-}
-#endif
+struct r300_winsys_screen *
+r300_winsys_screen(struct pipe_screen *screen);
#endif /* R300_WINSYS_H */