r300g: rebuild winsys and command submission to support multiple contexts
authorMarek Olšák <maraeo@gmail.com>
Tue, 13 Jul 2010 23:59:57 +0000 (01:59 +0200)
committerMarek Olšák <maraeo@gmail.com>
Fri, 16 Jul 2010 06:51:16 +0000 (08:51 +0200)
20 files changed:
src/gallium/drivers/r300/r300_cb.h
src/gallium/drivers/r300/r300_context.c
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_cs.h
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_flush.c
src/gallium/drivers/r300/r300_query.c
src/gallium/drivers/r300/r300_render.c
src/gallium/drivers/r300/r300_screen.c
src/gallium/drivers/r300/r300_screen.h
src/gallium/drivers/r300/r300_screen_buffer.c
src/gallium/drivers/r300/r300_screen_buffer.h
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r300/r300_texture.c
src/gallium/drivers/r300/r300_transfer.c
src/gallium/drivers/r300/r300_winsys.h
src/gallium/winsys/radeon/drm/radeon_buffer.h
src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
src/gallium/winsys/radeon/drm/radeon_r300.c
src/gallium/winsys/radeon/drm/radeon_winsys.h

index 61b2833..9d3d4fc 100644 (file)
@@ -89,9 +89,6 @@
     CB_DEBUG(cs_count = size;) \
 } while (0)
 
-#define BEGIN_CS_AS_CB(r300, size) \
-    BEGIN_CB(r300->rws->get_cs_pointer(r300->rws, size), size)
-
 #define END_CB do { \
     CB_DEBUG(if (cs_count != 0) \
         debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \
index 1beab76..0f7deca 100644 (file)
@@ -100,6 +100,8 @@ static void r300_destroy_context(struct pipe_context* context)
 
     r300_release_referenced_objects(r300);
 
+    r300->rws->cs_destroy(r300->cs);
+
     FREE(r300->aa_state.state);
     FREE(r300->blend_color_state.state);
     FREE(r300->clip_state.state);
@@ -354,6 +356,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     r300->context.destroy = r300_destroy_context;
 
+    r300->cs = rws->cs_create(rws);
+
     if (!r300screen->caps.has_tcl) {
         /* Create a Draw. This is used for SW TCL. */
         r300->draw = draw_create(&r300->context);
@@ -381,7 +385,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
     /* Render functions must be initialized after blitter. */
     r300_init_render_functions(r300);
 
-    rws->set_flush_cb(r300->rws, r300_flush_cb, r300);
+    rws->cs_set_flush(r300->cs, r300_flush_cb, r300);
 
     r300->upload_ib = u_upload_create(&r300->context,
                                      32 * 1024, 16,
@@ -433,11 +437,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
     return NULL;
 }
 
-boolean r300_check_cs(struct r300_context *r300, unsigned size)
-{
-    return size <= r300->rws->get_cs_free_dwords(r300->rws);
-}
-
 void r300_finish(struct r300_context *r300)
 {
     struct pipe_framebuffer_state *fb;
index df4299b..55cec88 100644 (file)
@@ -416,6 +416,8 @@ struct r300_context {
 
     /* The interface to the windowing system, etc. */
     struct r300_winsys_screen *rws;
+    /* The command stream. */
+    struct r300_winsys_cs *cs;
     /* Screen. */
     struct r300_screen *screen;
     /* Draw module. Used mostly for SW TCL. */
@@ -570,7 +572,6 @@ static INLINE struct r300_fragment_shader *r300_fs(struct r300_context *r300)
 struct pipe_context* r300_create_context(struct pipe_screen* screen,
                                          void *priv);
 
-boolean r300_check_cs(struct r300_context *r300, unsigned size);
 void r300_finish(struct r300_context *r300);
 void r300_flush_cb(void *data);
 
index 1db7da6..3beb625 100644 (file)
  */
 
 #define CS_LOCALS(context) \
-    struct r300_context* const cs_context_copy = (context); \
-    struct r300_winsys_screen *cs_winsys = cs_context_copy->rws; \
-    CS_DEBUG(int cs_count = 0; (void) cs_count;)
+    struct r300_winsys_cs *cs_copy = (context)->cs; \
+    struct r300_winsys_screen *cs_winsys = (context)->rws; \
+    int cs_count = 0; (void) cs_count; (void) cs_winsys;
 
 #define BEGIN_CS(size) do { \
-    assert(r300_check_cs(cs_context_copy, (size))); \
+    assert(size <= (cs_copy->ndw - cs_copy->cdw)); \
     CS_DEBUG(cs_count = size;) \
 } while (0)
 
 #define END_CS
 #endif
 
+
 /**
  * Writing pure DWORDs.
  */
 
 #define OUT_CS(value) do { \
-    cs_winsys->write_cs_dword(cs_winsys, (value)); \
+    cs_copy->ptr[cs_copy->cdw++] = (value); \
     CS_DEBUG(cs_count--;) \
 } while (0)
 
-#define OUT_CS_32F(value) do { \
-    cs_winsys->write_cs_dword(cs_winsys, fui(value)); \
-    CS_DEBUG(cs_count--;) \
-} while (0)
+#define OUT_CS_32F(value) \
+    OUT_CS(fui(value))
 
 #define OUT_CS_REG(register, value) do { \
-    assert(register); \
-    cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0(register, 0)); \
-    cs_winsys->write_cs_dword(cs_winsys, value); \
-    CS_DEBUG(cs_count -= 2;) \
+    OUT_CS(CP_PACKET0(register, 0)); \
+    OUT_CS(value); \
 } while (0)
 
 /* Note: This expects count to be the number of registers,
  * not the actual packet0 count! */
-#define OUT_CS_REG_SEQ(register, count) do { \
-    assert(register); \
-    cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0((register), ((count) - 1))); \
-    CS_DEBUG(cs_count--;) \
-} while (0)
+#define OUT_CS_REG_SEQ(register, count) \
+    OUT_CS(CP_PACKET0((register), ((count) - 1)))
 
-#define OUT_CS_TABLE(values, count) do { \
-    cs_winsys->write_cs_table(cs_winsys, values, count); \
-    CS_DEBUG(cs_count -= count;) \
-} while (0)
+#define OUT_CS_ONE_REG(register, count) \
+    OUT_CS(CP_PACKET0((register), ((count) - 1)) | RADEON_ONE_REG_WR)
 
-#define OUT_CS_ONE_REG(register, count) do { \
-    assert(register); \
-    cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0((register), ((count) - 1)) | RADEON_ONE_REG_WR); \
-    CS_DEBUG(cs_count--;) \
-} while (0)
+#define OUT_CS_PKT3(op, count) \
+    OUT_CS(CP_PACKET3(op, count))
 
-#define OUT_CS_PKT3(op, count) do { \
-    cs_winsys->write_cs_dword(cs_winsys, CP_PACKET3(op, count)); \
-    CS_DEBUG(cs_count--;) \
+#define OUT_CS_TABLE(values, count) do { \
+    memcpy(cs_copy->ptr + cs_copy->cdw, values, count * 4); \
+    cs_copy->cdw += count; \
+    CS_DEBUG(cs_count -= count;) \
 } while (0)
 
 
  * Writing relocations.
  */
 
-#define OUT_CS_RELOC(bo, offset, rd, wd, flags) do { \
+#define OUT_CS_RELOC(bo, offset, rd, wd) do { \
     assert(bo); \
-    cs_winsys->write_cs_dword(cs_winsys, offset); \
-    cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \
-    CS_DEBUG(cs_count -= 3;) \
+    OUT_CS(offset); \
+    cs_winsys->cs_write_reloc(cs_copy, bo, rd, wd); \
+    CS_DEBUG(cs_count -= 2;) \
 } while (0)
 
-#define OUT_CS_BUF_RELOC(bo, offset, rd, wd, flags) do { \
+#define OUT_CS_BUF_RELOC(bo, offset, rd, wd) do { \
     assert(bo); \
-    OUT_CS_RELOC(r300_buffer(bo)->buf, offset, rd, wd, flags); \
+    OUT_CS_RELOC(r300_buffer(bo)->buf, offset, rd, wd); \
 } while (0)
 
-#define OUT_CS_TEX_RELOC(tex, offset, rd, wd, flags) do { \
+#define OUT_CS_TEX_RELOC(tex, offset, rd, wd) do { \
     assert(tex); \
-    OUT_CS_RELOC(tex->buffer, offset, rd, wd, flags); \
+    OUT_CS_RELOC(tex->buffer, offset, rd, wd); \
 } while (0)
 
-#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \
+#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd) do { \
     assert(bo); \
-    cs_winsys->write_cs_reloc(cs_winsys, r300_buffer(bo)->buf, rd, wd, flags); \
+    cs_winsys->cs_write_reloc(cs_copy, r300_buffer(bo)->buf, rd, wd); \
     CS_DEBUG(cs_count -= 2;) \
 } while (0)
 
 
 #define WRITE_CS_TABLE(values, count) do { \
     CS_DEBUG(assert(cs_count == 0);) \
-    cs_winsys->write_cs_table(cs_winsys, values, count); \
+    memcpy(cs_copy->ptr + cs_copy->cdw, values, count * 4); \
+    cs_copy->cdw += count; \
 } while (0)
 
 #endif /* R300_CS_H */
index daae6dd..10d9e67 100644 (file)
@@ -314,10 +314,10 @@ void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state)
 
     if (aa->dest) {
         OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 1);
-        OUT_CS_RELOC(aa->dest->buffer, aa->dest->offset, 0, aa->dest->domain, 0);
+        OUT_CS_RELOC(aa->dest->buffer, aa->dest->offset, 0, aa->dest->domain);
 
         OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_PITCH, 1);
-        OUT_CS_RELOC(aa->dest->buffer, aa->dest->pitch, 0, aa->dest->domain, 0);
+        OUT_CS_RELOC(aa->dest->buffer, aa->dest->pitch, 0, aa->dest->domain);
     }
 
     OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, aa->aaresolve_ctl);
@@ -347,10 +347,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
         surf = r300_surface(fb->cbufs[i]);
 
         OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1);
-        OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain, 0);
+        OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain);
 
         OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1);
-        OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain, 0);
+        OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain);
     }
 
     /* Set up the ZB part of the CBZB clear. */
@@ -360,10 +360,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
         OUT_CS_REG(R300_ZB_FORMAT, surf->cbzb_format);
 
         OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
-        OUT_CS_RELOC(surf->buffer, surf->cbzb_midpoint_offset, 0, surf->domain, 0);
+        OUT_CS_RELOC(surf->buffer, surf->cbzb_midpoint_offset, 0, surf->domain);
 
         OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
-        OUT_CS_RELOC(surf->buffer, surf->cbzb_pitch, 0, surf->domain, 0);
+        OUT_CS_RELOC(surf->buffer, surf->cbzb_pitch, 0, surf->domain);
     }
     /* Set up a zbuffer. */
     else if (fb->zsbuf) {
@@ -372,10 +372,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
         OUT_CS_REG(R300_ZB_FORMAT, surf->format);
 
         OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
-        OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain, 0);
+        OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain);
 
         OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
-        OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain, 0);
+        OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain);
 
         /* HiZ RAM. */
         if (r300->screen->caps.has_hiz) {
@@ -512,13 +512,13 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
             OUT_CS_REG(R300_SU_REG_DEST, 1 << 3);
             OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
             OUT_CS_RELOC(buf, (query->num_results + 3) * 4,
-                    0, query->domain, 0);
+                    0, query->domain);
         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(buf, (query->num_results + 2) * 4,
-                    0, query->domain, 0);
+                    0, query->domain);
         case 2:
             /* pipe 1 only */
             /* As mentioned above, accomodate RV380 and older. */
@@ -526,13 +526,13 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
                     1 << (caps->high_second_pipe ? 3 : 1));
             OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
             OUT_CS_RELOC(buf, (query->num_results + 1) * 4,
-                    0, query->domain, 0);
+                    0, query->domain);
         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(buf, (query->num_results + 0) * 4,
-                    0, query->domain, 0);
+                    0, query->domain);
             break;
         default:
             fprintf(stderr, "r300: Implementation error: Chipset reports %d"
@@ -554,7 +554,7 @@ static void rv530_emit_query_end_single_z(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(buf, query->num_results * 4, 0, query->domain, 0);
+    OUT_CS_RELOC(buf, query->num_results * 4, 0, query->domain);
     OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
     END_CS;
 }
@@ -568,10 +568,10 @@ static void rv530_emit_query_end_double_z(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(buf, (query->num_results + 0) * 4, 0, query->domain, 0);
+    OUT_CS_RELOC(buf, (query->num_results + 0) * 4, 0, query->domain);
     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(buf, (query->num_results + 1) * 4, 0, query->domain, 0);
+    OUT_CS_RELOC(buf, (query->num_results + 1) * 4, 0, query->domain);
     OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
     END_CS;
 }
@@ -731,7 +731,7 @@ void r300_emit_textures_state(struct r300_context *r300,
 
             OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1);
             OUT_CS_TEX_RELOC(tex, texstate->format.tile_config, tex->domain,
-                             0, 0);
+                             0);
         }
     }
     END_CS;
@@ -774,7 +774,7 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed)
 
     for (i = 0; i < aos_count; i++) {
         buf = r300_buffer(vbuf[velem[i].vertex_buffer_index].buffer);
-        OUT_CS_BUF_RELOC_NO_OFFSET(&buf->b.b, buf->domain, 0, 0);
+        OUT_CS_BUF_RELOC_NO_OFFSET(&buf->b.b, buf->domain, 0);
     }
     END_CS;
 }
@@ -799,7 +799,7 @@ void r300_emit_aos_swtcl(struct r300_context *r300, boolean indexed)
     OUT_CS(r300->vertex_info.size |
             (r300->vertex_info.size << 8));
     OUT_CS(r300->vbo_offset);
-    OUT_CS_BUF_RELOC(r300->vbo, 0, r300_buffer(r300->vbo)->domain, 0, 0);
+    OUT_CS_BUF_RELOC(r300->vbo, 0, r300_buffer(r300->vbo)->domain, 0);
     END_CS;
 }
 
@@ -985,28 +985,22 @@ void r300_emit_buffer_validate(struct r300_context *r300,
     }
 
     /* Clean out BOs. */
-    r300->rws->reset_bos(r300->rws);
+    r300->rws->cs_reset_buffers(r300->cs);
 
 validate:
     /* Color buffers... */
     for (i = 0; i < fb->nr_cbufs; i++) {
         tex = r300_texture(fb->cbufs[i]->texture);
         assert(tex && tex->buffer && "cbuf is marked, but NULL!");
-        if (!r300_add_texture(r300->rws, tex, 0,
-                              r300_surface(fb->cbufs[i])->domain)) {
-            r300->context.flush(&r300->context, 0, NULL);
-            goto validate;
-        }
+        r300->rws->cs_add_buffer(r300->cs, tex->buffer, 0,
+                                 r300_surface(fb->cbufs[i])->domain);
     }
     /* ...depth buffer... */
     if (fb->zsbuf) {
         tex = r300_texture(fb->zsbuf->texture);
         assert(tex && tex->buffer && "zsbuf is marked, but NULL!");
-        if (!r300_add_texture(r300->rws, tex, 0,
-                              r300_surface(fb->zsbuf)->domain)) {
-            r300->context.flush(&r300->context, 0, NULL);
-            goto validate;
-        }
+        r300->rws->cs_add_buffer(r300->cs, tex->buffer, 0,
+                                 r300_surface(fb->zsbuf)->domain);
     }
     /* ...textures... */
     for (i = 0; i < texstate->count; i++) {
@@ -1015,48 +1009,31 @@ validate:
         }
 
         tex = r300_texture(texstate->sampler_views[i]->base.texture);
-        if (!r300_add_texture(r300->rws, tex, tex->domain, 0)) {
-            r300->context.flush(&r300->context, 0, NULL);
-            goto validate;
-        }
+        r300->rws->cs_add_buffer(r300->cs, tex->buffer, tex->domain, 0);
     }
     /* ...occlusion query buffer... */
-    if (r300->query_current) {
-        if (!r300->rws->add_buffer(r300->rws, r300->query_current->buffer,
-                                   0, r300->query_current->domain)) {
-            r300->context.flush(&r300->context, 0, NULL);
-            goto validate;
-        }
-    }
+    if (r300->query_current)
+        r300->rws->cs_add_buffer(r300->cs, r300->query_current->buffer,
+                                 0, r300->query_current->domain);
     /* ...vertex buffer for SWTCL path... */
-    if (r300->vbo) {
-        if (!r300_add_buffer(r300->rws, r300->vbo,
-                            r300_buffer(r300->vbo)->domain, 0)) {
-            r300->context.flush(&r300->context, 0, NULL);
-            goto validate;
-        }
-    }
+    if (r300->vbo)
+        r300->rws->cs_add_buffer(r300->cs, r300_buffer(r300->vbo)->buf,
+                                 r300_buffer(r300->vbo)->domain, 0);
     /* ...vertex buffers for HWTCL path... */
     if (do_validate_vertex_buffers) {
         for (i = 0; i < r300->velems->count; i++) {
             pbuf = vbuf[velem[i].vertex_buffer_index].buffer;
 
-            if (!r300_add_buffer(r300->rws, pbuf,
-                                r300_buffer(pbuf)->domain, 0)) {
-               r300->context.flush(&r300->context, 0, NULL);
-                goto validate;
-            }
+            r300->rws->cs_add_buffer(r300->cs, r300_buffer(pbuf)->buf,
+                                     r300_buffer(pbuf)->domain, 0);
         }
     }
     /* ...and index buffer for HWTCL path. */
-    if (index_buffer) {
-        if (!r300_add_buffer(r300->rws, index_buffer,
-                            r300_buffer(index_buffer)->domain, 0)) {
-            r300->context.flush(&r300->context, 0, NULL);
-            goto validate;
-        }
-    }
-    if (!r300->rws->validate(r300->rws)) {
+    if (index_buffer)
+        r300->rws->cs_add_buffer(r300->cs, r300_buffer(index_buffer)->buf,
+                                 r300_buffer(index_buffer)->domain, 0);
+
+    if (!r300->rws->cs_validate(r300->cs)) {
         r300->context.flush(&r300->context, 0, NULL);
         if (invalid) {
             /* Well, hell. */
index 6f31ba1..9e5bfeb 100644 (file)
@@ -52,7 +52,7 @@ static void r300_flush(struct pipe_context* pipe,
         r300_emit_query_end(r300);
 
         r300->flush_counter++;
-        r300->rws->flush_cs(r300->rws);
+        r300->rws->cs_flush(r300->cs);
         r300->dirty_hw = 0;
 
         /* New kitchen sink, baby. */
index 10086ee..5b0121c 100644 (file)
@@ -57,7 +57,9 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe,
     insert_at_tail(&r300->query_list, q);
 
     /* Open up the occlusion query buffer. */
-    q->buffer = r300->rws->buffer_create(r300->rws, 4096, 0, q->domain, q->buffer_size);
+    q->buffer = r300->rws->buffer_create(r300->rws, q->buffer_size, 4096,
+                                         PIPE_BIND_CUSTOM, PIPE_USAGE_STREAM,
+                                         q->domain);
 
     return (struct pipe_query*)q;
 }
@@ -134,7 +136,7 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
 
     flags = PIPE_TRANSFER_READ | (!wait ? PIPE_TRANSFER_DONTBLOCK : 0);
 
-    map = r300->rws->buffer_map(r300->rws, q->buffer, flags);
+    map = r300->rws->buffer_map(r300->rws, q->buffer, r300->cs, flags);
     if (!map)
         return FALSE;
 
index 970cb68..d30de1a 100644 (file)
@@ -229,7 +229,7 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
     cs_dwords += end_dwords;
 
     /* Reserve requested CS space. */
-    if (!r300_check_cs(r300, cs_dwords)) {
+    if (cs_dwords > (r300->cs->ndw - r300->cs->cdw)) {
         r300->context.flush(&r300->context, 0, NULL);
         flushed = TRUE;
     }
@@ -331,7 +331,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
     uint32_t* mapelem[PIPE_MAX_ATTRIBS];
     struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0};
 
-    CB_LOCALS;
+    CS_LOCALS(r300);
 
     /* Calculate the vertex size, offsets, strides etc. and map the buffers. */
     for (i = 0; i < vertex_element_count; i++) {
@@ -356,24 +356,24 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
 
     r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0, NULL);
 
-    BEGIN_CS_AS_CB(r300, dwords);
-    OUT_CB_REG(R300_GA_COLOR_CONTROL,
+    BEGIN_CS(dwords);
+    OUT_CS_REG(R300_GA_COLOR_CONTROL,
             r300_provoking_vertex_fixes(r300, mode));
-    OUT_CB_REG(R300_VAP_VTX_SIZE, vertex_size);
-    OUT_CB_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
-    OUT_CB(count - 1);
-    OUT_CB(0);
-    OUT_CB_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size);
-    OUT_CB(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) |
+    OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
+    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));
 
     /* Emit vertices. */
     for (v = 0; v < count; v++) {
         for (i = 0; i < vertex_element_count; i++) {
-            OUT_CB_TABLE(&mapelem[i][stride[i] * v], size[i]);
+            OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]);
         }
     }
-    END_CB;
+    END_CS;
 
     /* Unmap buffers. */
     for (i = 0; i < vertex_element_count; i++) {
@@ -474,7 +474,7 @@ static void r300_emit_draw_elements(struct r300_context *r300,
            (0 << R300_INDX_BUFFER_SKIP_SHIFT));
     OUT_CS(offset_dwords << 2);
     OUT_CS_BUF_RELOC(indexBuffer, count_dwords,
-                    r300_buffer(indexBuffer)->domain, 0, 0);
+                     r300_buffer(indexBuffer)->domain, 0);
 
     END_CS;
 }
@@ -929,7 +929,7 @@ static void r300_render_draw_elements(struct vbuf_render* render,
         NULL, 256, 0, 0, &end_cs_dwords);
 
     while (count) {
-        free_dwords = r300->rws->get_cs_free_dwords(r300->rws);
+        free_dwords = r300->cs->ndw - r300->cs->cdw;
 
         short_count = MIN2(count, (free_dwords - end_cs_dwords - 6) * 2);
 
@@ -1039,7 +1039,7 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter,
     unsigned dwords = 13 + vertex_size +
                       (type == UTIL_BLITTER_ATTRIB_TEXCOORD ? 7 : 0);
     const float zeros[4] = {0, 0, 0, 0};
-    CB_LOCALS;
+    CS_LOCALS(r300);
 
     if (type == UTIL_BLITTER_ATTRIB_TEXCOORD)
         r300->sprite_coord_enable = 1;
@@ -1054,45 +1054,45 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter,
 
     DBG(r300, DBG_DRAW, "r300: draw_rectangle\n");
 
-    BEGIN_CS_AS_CB(r300, dwords);
+    BEGIN_CS(dwords);
     /* Set up GA. */
-    OUT_CB_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16));
+    OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16));
 
     if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) {
         /* Set up the GA to generate texcoords. */
-        OUT_CB_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
+        OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
                    (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT));
-        OUT_CB_REG_SEQ(R300_GA_POINT_S0, 4);
-        OUT_CB_32F(attrib[0]);
-        OUT_CB_32F(attrib[3]);
-        OUT_CB_32F(attrib[2]);
-        OUT_CB_32F(attrib[1]);
+        OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4);
+        OUT_CS_32F(attrib[0]);
+        OUT_CS_32F(attrib[3]);
+        OUT_CS_32F(attrib[2]);
+        OUT_CS_32F(attrib[1]);
     }
 
     /* Set up VAP controls. */
-    OUT_CB_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
-    OUT_CB_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT);
-    OUT_CB_REG(R300_VAP_VTX_SIZE, vertex_size);
-    OUT_CB_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
-    OUT_CB(1);
-    OUT_CB(0);
+    OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
+    OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT);
+    OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
+    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
+    OUT_CS(1);
+    OUT_CS(0);
 
     /* Draw. */
-    OUT_CB_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size);
-    OUT_CB(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) |
+    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size);
+    OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) |
            R300_VAP_VF_CNTL__PRIM_POINTS);
 
-    OUT_CB_32F(x1 + width * 0.5f);
-    OUT_CB_32F(y1 + height * 0.5f);
-    OUT_CB_32F(depth);
-    OUT_CB_32F(1);
+    OUT_CS_32F(x1 + width * 0.5f);
+    OUT_CS_32F(y1 + height * 0.5f);
+    OUT_CS_32F(depth);
+    OUT_CS_32F(1);
 
     if (vertex_size == 8) {
         if (!attrib)
             attrib = zeros;
-        OUT_CB_TABLE(attrib, 4);
+        OUT_CS_TABLE(attrib, 4);
     }
-    END_CB;
+    END_CS;
 
     /* Restore the state. */
     r300->clip_state.dirty = TRUE;
index a3b0855..f28b055 100644 (file)
@@ -420,9 +420,3 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws)
 
     return &r300screen->screen;
 }
-
-struct r300_winsys_screen *
-r300_winsys_screen(struct pipe_screen *screen)
-{
-    return r300_screen(screen)->rws;
-}
index c6b4b57..5827023 100644 (file)
@@ -30,6 +30,8 @@
 
 #include <stdio.h>
 
+struct r300_winsys_screen;
+
 struct r300_screen {
     /* Parent class */
     struct pipe_screen screen;
@@ -44,11 +46,16 @@ struct r300_screen {
 };
 
 
-/* Convenience cast wrapper. */
+/* Convenience cast wrappers. */
 static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) {
     return (struct r300_screen*)screen;
 }
 
+static INLINE struct r300_winsys_screen *
+r300_winsys_screen(struct pipe_screen *screen) {
+    return r300_screen(screen)->rws;
+}
+
 /* Debug functionality. */
 
 /**
index f49f36b..15d3f25 100644 (file)
@@ -43,7 +43,7 @@ unsigned r300_buffer_is_referenced(struct pipe_context *context,
     if (r300_buffer_is_user_buffer(buf))
        return PIPE_UNREFERENCED;
 
-    if (r300->rws->is_buffer_referenced(r300->rws, rbuf->buf, domain))
+    if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->buf, domain))
         return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
 
     return PIPE_UNREFERENCED;
@@ -144,6 +144,7 @@ static void *
 r300_buffer_transfer_map( struct pipe_context *pipe,
                          struct pipe_transfer *transfer )
 {
+    struct r300_context *r300 = r300_context(pipe);
     struct r300_screen *r300screen = r300_screen(pipe->screen);
     struct r300_winsys_screen *rws = r300screen->rws;
     struct r300_buffer *rbuf = r300_buffer(transfer->resource);
@@ -170,23 +171,19 @@ r300_buffer_transfer_map( struct pipe_context *pipe,
                rws->buffer_reference(rws, &rbuf->buf, NULL);
 
                rbuf->num_ranges = 0;
-               rbuf->buf = r300screen->rws->buffer_create(r300screen->rws, 16,
-                                                     rbuf->b.b.bind,
-                                                      rbuf->domain,
-                                                     rbuf->b.b.width0);
+                rbuf->buf =
+                    r300screen->rws->buffer_create(r300screen->rws,
+                                                   rbuf->b.b.width0, 16,
+                                                   rbuf->b.b.bind,
+                                                   rbuf->b.b.usage,
+                                                   rbuf->domain);
                break;
            }
        }
     }
 
 just_map:
-    /* XXX buffer_map might flush.
-     * We cannot flush here because there is a buffer manager between
-     * the context and winsys, and it does some magic to make the driver
-     * fast. This is a workaround for the case of multiple contexts. */
-    rws->set_flush_cb(rws, r300_flush_cb, pipe);
-
-    map = rws->buffer_map(rws, rbuf->buf, transfer->usage);
+    map = rws->buffer_map(rws, rbuf->buf, r300->cs, transfer->usage);
 
     if (map == NULL)
         return NULL;
@@ -273,11 +270,11 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
     rbuf->b.b.screen = screen;
     rbuf->domain = R300_DOMAIN_GTT;
 
-    rbuf->buf = r300screen->rws->buffer_create(r300screen->rws,
-                                         alignment,
-                                         rbuf->b.b.bind,
-                                          rbuf->domain,
-                                         rbuf->b.b.width0);
+    rbuf->buf =
+        r300screen->rws->buffer_create(r300screen->rws,
+                                       rbuf->b.b.width0, alignment,
+                                       rbuf->b.b.bind, rbuf->b.b.usage,
+                                       rbuf->domain);
 
     if (!rbuf->buf)
        goto error2;
index ff35585..4f7c0ec 100644 (file)
@@ -97,23 +97,4 @@ 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);
-}
-
 #endif
index f4c6a26..8214bcc 100644 (file)
@@ -617,13 +617,13 @@ static void r300_tex_set_tiling_flags(struct r300_context *r300,
     if (tex->mip_macrotile[tex->surface_level] != tex->mip_macrotile[level]) {
         /* Tiling determines how DRM treats the buffer data.
          * We must flush CS when changing it if the buffer is referenced. */
-        if (r300->rws->is_buffer_referenced(r300->rws, tex->buffer, R300_REF_CS))
+        if (r300->rws->cs_is_buffer_referenced(r300->cs,
+                                               tex->buffer, R300_REF_CS))
             r300->context.flush(&r300->context, 0, NULL);
 
         r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
-                tex->pitch[0] * util_format_get_blocksize(tex->b.b.format),
-                tex->microtile,
-                tex->mip_macrotile[level]);
+                tex->microtile, tex->mip_macrotile[level],
+                tex->pitch[0] * util_format_get_blocksize(tex->b.b.format));
 
         tex->surface_level = level;
     }
index e8b1d67..5750bc4 100644 (file)
@@ -908,7 +908,8 @@ static unsigned r300_texture_is_referenced(struct pipe_context *context,
     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))
+    if (r300->rws->cs_is_buffer_referenced(r300->cs,
+                                           rtex->buffer, R300_REF_CS))
         return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
 
     return PIPE_UNREFERENCED;
@@ -935,8 +936,9 @@ static boolean r300_texture_get_handle(struct pipe_screen* screen,
         return FALSE;
     }
 
-    return rws->buffer_get_handle(rws, tex->buffer, whandle,
-                    r300_texture_get_stride(r300_screen(screen), tex, 0));
+    return rws->buffer_get_handle(rws, tex->buffer,
+                    r300_texture_get_stride(r300_screen(screen), tex, 0),
+                    whandle);
 }
 
 struct u_resource_vtbl r300_texture_vtbl = 
@@ -1005,8 +1007,8 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
                   R300_DOMAIN_GTT :
                   R300_DOMAIN_VRAM | R300_DOMAIN_GTT;
 
-    tex->buffer = rws->buffer_create(rws, 2048, base->bind, tex->domain,
-                                     tex->size);
+    tex->buffer = rws->buffer_create(rws, tex->size, 2048, base->bind,
+                                     base->usage, tex->domain);
 
     if (!tex->buffer) {
        FREE(tex);
@@ -1014,9 +1016,8 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
     }
 
     rws->buffer_set_tiling(rws, tex->buffer,
-            tex->pitch[0] * util_format_get_blocksize(tex->b.b.format),
-            tex->microtile,
-            tex->macrotile);
+            tex->microtile, tex->macrotile,
+            tex->pitch[0] * util_format_get_blocksize(tex->b.b.format));
 
     return (struct pipe_resource*)tex;
 }
@@ -1176,9 +1177,8 @@ r300_texture_from_handle(struct pipe_screen* screen,
 
     if (override_zb_flags) {
         rws->buffer_set_tiling(rws, tex->buffer,
-                tex->pitch[0] * util_format_get_blocksize(tex->b.b.format),
-                tex->microtile,
-                tex->macrotile);
+                tex->microtile, tex->macrotile,
+                tex->pitch[0] * util_format_get_blocksize(tex->b.b.format));
     }
     return (struct pipe_resource*)tex;
 }
index 2eb93e1..3cc4c8c 100644 (file)
@@ -91,19 +91,22 @@ r300_texture_get_transfer(struct pipe_context *ctx,
                          unsigned usage,
                          const struct pipe_box *box)
 {
+    struct r300_context *r300 = r300_context(ctx);
     struct r300_texture *tex = r300_texture(texture);
     struct r300_screen *r300screen = r300_screen(ctx->screen);
     struct r300_transfer *trans;
     struct pipe_resource base;
     boolean referenced_cs, referenced_hw, blittable;
 
-    referenced_cs = r300screen->rws->is_buffer_referenced(
-                                r300screen->rws, tex->buffer, R300_REF_CS);
+    referenced_cs =
+        r300->rws->cs_is_buffer_referenced(r300->cs,
+                                           tex->buffer, R300_REF_CS);
     if (referenced_cs) {
         referenced_hw = TRUE;
     } else {
-        referenced_hw = r300screen->rws->is_buffer_referenced(
-                                r300screen->rws, tex->buffer, R300_REF_HW);
+        referenced_hw =
+            r300->rws->cs_is_buffer_referenced(r300->cs,
+                                               tex->buffer, R300_REF_HW);
     }
 
     blittable = ctx->screen->is_format_supported(
@@ -231,6 +234,7 @@ void r300_texture_transfer_destroy(struct pipe_context *ctx,
 void* r300_texture_transfer_map(struct pipe_context *ctx,
                                struct pipe_transfer *transfer)
 {
+    struct r300_context *r300 = r300_context(ctx);
     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);
@@ -242,10 +246,11 @@ void* r300_texture_transfer_map(struct pipe_context *ctx,
          * (no offset needed). */
         return rws->buffer_map(rws,
                                r300transfer->detiled_texture->buffer,
+                               r300->cs,
                                transfer->usage);
     } else {
         /* Tiling is disabled. */
-        map = rws->buffer_map(rws, tex->buffer,
+        map = rws->buffer_map(rws, tex->buffer, r300->cs,
                               transfer->usage);
 
         if (!map) {
index 7687eac..7e115c2 100644 (file)
@@ -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"),
 #ifndef R300_WINSYS_H
 #define R300_WINSYS_H
 
-/* 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. */
+/* The public winsys interface header for the r300 pipe driver.
+ * Any winsys hosting this pipe needs to implement r300_winsys_screen and then
+ * call r300_screen_create to start things. */
 
 #include "pipe/p_defines.h"
 #include "pipe/p_state.h"
 
 #include "r300_defines.h"
 
+struct r300_winsys_screen;
+
 struct r300_winsys_buffer;
 
+struct r300_winsys_cs {
+    uint32_t *ptr;      /* Pointer to the beginning of the CS. */
+    unsigned cdw;       /* Number of used dwords. */
+    unsigned ndw;       /* Size of the CS in dwords. */
+};
+
 enum r300_value_id {
     R300_VID_PCI_ID,
     R300_VID_GB_PIPES,
@@ -48,120 +57,250 @@ enum r300_reference_domain { /* bitfield */
 };
 
 struct r300_winsys_screen {
+    /**
+     * Destroy this winsys.
+     *
+     * \param ws        The winsys this function is called from.
+     */
     void (*destroy)(struct r300_winsys_screen *ws);
-    
+
     /**
+     * Query a system value from a winsys.
+     *
+     * \param ws        The winsys this function is called from.
+     * \param vid       One of the R300_VID_* enums.
+     */
+    uint32_t (*get_value)(struct r300_winsys_screen *ws,
+                          enum r300_value_id vid);
+
+    /**************************************************************************
      * 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...).
+     *************************************************************************/
+
+    /**
+     * Create a buffer object.
      *
-     * 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.
+     * \param ws        The winsys this function is called from.
+     * \param size      The size to allocate.
+     * \param alignment An alignment of the buffer in memory.
+     * \param bind      A bitmask of the PIPE_BIND_* flags.
+     * \param usage     A bitmask of the PIPE_USAGE_* flags.
+     * \param domain    A bitmask of the R300_DOMAIN_* flags.
+     * \return          The created buffer object.
      */
     struct r300_winsys_buffer *(*buffer_create)(struct r300_winsys_screen *ws,
-                                               unsigned alignment,
-                                               unsigned usage,
-                                                enum r300_buffer_domain domain,
-                                               unsigned size);
+                                                unsigned size,
+                                                unsigned alignment,
+                                                unsigned bind,
+                                                unsigned usage,
+                                                enum r300_buffer_domain domain);
 
     /**
-     * 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.
+     * Reference a buffer object (assign with reference counting).
+     *
+     * \param ws        The winsys this function is called from.
+     * \param pdst      A destination pointer to set the source buffer to.
+     * \param src       A source buffer object.
      */
-    void *(*buffer_map)( struct r300_winsys_screen *ws,
-                        struct r300_winsys_buffer *buf,
-                        unsigned usage);
+    void (*buffer_reference)(struct r300_winsys_screen *ws,
+                             struct r300_winsys_buffer **pdst,
+                             struct r300_winsys_buffer *src);
 
-    void (*buffer_unmap)( struct r300_winsys_screen *ws,
-                         struct r300_winsys_buffer *buf );
+    /**
+     * Map the entire data store of a buffer object into the client's address
+     * space.
+     *
+     * \param ws        The winsys this function is called from.
+     * \param buf       A winsys buffer object to map.
+     * \param cs        A command stream to flush if the buffer is referenced by it.
+     * \param usage     A bitmask of the PIPE_TRANSFER_* flags.
+     * \return          The pointer at the beginning of the buffer.
+     */
+    void *(*buffer_map)(struct r300_winsys_screen *ws,
+                        struct r300_winsys_buffer *buf,
+                        struct r300_winsys_cs *cs,
+                        enum pipe_transfer_usage usage);
 
-    void (*buffer_destroy)( struct r300_winsys_buffer *buf );
+    /**
+     * Unmap a buffer object from the client's address space.
+     *
+     * \param ws        The winsys this function is called from.
+     * \param buf       A winsys buffer object to unmap.
+     */
+    void (*buffer_unmap)(struct r300_winsys_screen *ws,
+                         struct r300_winsys_buffer *buf);
 
+    /**
+     * Wait for a buffer object until it is not used by a GPU. This is
+     * equivalent to a fence placed after the last command using the buffer,
+     * and synchronizing to the fence.
+     *
+     * \param ws        The winsys this function is called from.
+     * \param buf       A winsys buffer object to wait for.
+     */
+    void (*buffer_wait)(struct r300_winsys_screen *ws,
+                        struct r300_winsys_buffer *buf);
 
-    void (*buffer_reference)(struct r300_winsys_screen *rws,
-                            struct r300_winsys_buffer **pdst,
-                            struct r300_winsys_buffer *src);
+    /**
+     * Return tiling flags describing a memory layout of a buffer object.
+     *
+     * \param ws        The winsys this function is called from.
+     * \param buf       A winsys buffer object to get the flags from.
+     * \param macrotile A pointer to the return value of the microtile flag.
+     * \param microtile A pointer to the return value of the macrotile flag.
+     *
+     * \note microtile and macrotile are not bitmasks!
+     */
+    void (*buffer_get_tiling)(struct r300_winsys_screen *ws,
+                              struct r300_winsys_buffer *buf,
+                              enum r300_buffer_tiling *microtile,
+                              enum r300_buffer_tiling *macrotile);
 
-    void (*buffer_wait)(struct r300_winsys_screen *rws,
-                        struct r300_winsys_buffer *buf);
+    /**
+     * Set tiling flags describing a memory layout of a buffer object.
+     *
+     * \param ws        The winsys this function is called from.
+     * \param buf       A winsys buffer object to set the flags for.
+     * \param macrotile A macrotile flag.
+     * \param microtile A microtile flag.
+     * \param stride    A stride of the buffer in bytes, for texturing.
+     *
+     * \note microtile and macrotile are not bitmasks!
+     */
+    void (*buffer_set_tiling)(struct r300_winsys_screen *ws,
+                              struct r300_winsys_buffer *buf,
+                              enum r300_buffer_tiling microtile,
+                              enum r300_buffer_tiling macrotile,
+                              unsigned stride);
 
-    /* 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,
-                          enum r300_buffer_domain rd,
-                          enum r300_buffer_domain wd);
+    /**
+     * Get a winsys buffer from a winsys handle. The internal structure
+     * of the handle is platform-specific and only a winsys should access it.
+     *
+     * \param ws        The winsys this function is called from.
+     * \param whandle   A winsys handle pointer as was received from a state
+     *                  tracker.
+     * \param stride    A pointer to the stride return variable.
+     *                  The stride is in bytes.
+     */
+    struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *ws,
+                                                     struct winsys_handle *whandle,
+                                                     unsigned *stride);
 
+    /**
+     * Get a winsys handle from a winsys buffer. The internal structure
+     * of the handle is platform-specific and only a winsys should access it.
+     *
+     * \param ws        The winsys this function is called from.
+     * \param buf       A winsys buffer object to get the handle from.
+     * \param whandle   A winsys handle pointer.
+     * \param stride    A stride of the buffer in bytes, for texturing.
+     * \return          TRUE on success.
+     */
+    boolean (*buffer_get_handle)(struct r300_winsys_screen *ws,
+                                 struct r300_winsys_buffer *buf,
+                                 unsigned stride,
+                                 struct winsys_handle *whandle);
 
-    /* Revalidate all currently setup pipe_buffers.
-     * Returns TRUE if a flush is required. */
-    boolean (*validate)(struct r300_winsys_screen* winsys);
+    /**************************************************************************
+     * Command submission.
+     *
+     * Each pipe context should create its own command stream and submit
+     * commands independently of other contexts.
+     *************************************************************************/
 
-    /* Return the number of free dwords in CS. */
-    unsigned (*get_cs_free_dwords)(struct r300_winsys_screen *winsys);
+    /**
+     * Create a command stream.
+     *
+     * \param ws        The winsys this function is called from.
+     */
+    struct r300_winsys_cs *(*cs_create)(struct r300_winsys_screen *ws);
 
-    /* Return the pointer to the first free dword in CS and assume a pipe
-     * driver wants to fill "count" dwords. */
-    uint32_t *(*get_cs_pointer)(struct r300_winsys_screen *winsys,
-                                unsigned count);
+    /**
+     * Destroy a command stream.
+     *
+     * \param cs        A command stream to destroy.
+     */
+    void (*cs_destroy)(struct r300_winsys_cs *cs);
 
-    /* Write a dword to the command buffer. */
-    void (*write_cs_dword)(struct r300_winsys_screen* winsys, uint32_t dword);
+    /**
+     * Add a buffer object to the list of buffers to validate.
+     *
+     * \param cs        A command stream to add buffer for validation against.
+     * \param buf       A winsys buffer to validate.
+     * \param rd        A read domain containing a bitmask
+     *                  of the R300_DOMAIN_* flags.
+     * \param wd        A write domain containing a bitmask
+     *                  of the R300_DOMAIN_* flags.
+     */
+    void (*cs_add_buffer)(struct r300_winsys_cs *cs,
+                          struct r300_winsys_buffer *buf,
+                          enum r300_buffer_domain rd,
+                          enum r300_buffer_domain wd);
 
-    /* Write a table of dwords to the command buffer. */
-    void (*write_cs_table)(struct r300_winsys_screen* winsys,
-                           const void *dwords, unsigned count);
+    /**
+     * Revalidate all currently set up winsys buffers.
+     * Returns TRUE if a flush is required.
+     *
+     * \param cs        A command stream to validate.
+     */
+    boolean (*cs_validate)(struct r300_winsys_cs *cs);
 
-    /* Write a relocated dword to the command buffer. */
-    void (*write_cs_reloc)(struct r300_winsys_screen *winsys,
+    /**
+     * Write a relocated dword to a command buffer.
+     *
+     * \param cs        A command stream the relocation is written to.
+     * \param buf       A winsys buffer to write the relocation for.
+     * \param rd        A read domain containing a bitmask of the R300_DOMAIN_* flags.
+     * \param wd        A write domain containing a bitmask of the R300_DOMAIN_* flags.
+     */
+    void (*cs_write_reloc)(struct r300_winsys_cs *cs,
                            struct r300_winsys_buffer *buf,
                            enum r300_buffer_domain rd,
-                           enum r300_buffer_domain wd,
-                           uint32_t flags);
+                           enum r300_buffer_domain wd);
 
-    /* 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);
+    /**
+     * Flush a command stream.
+     *
+     * \param cs        A command stream to flush.
+     */
+    void (*cs_flush)(struct r300_winsys_cs *cs);
 
-    struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *winsys,
-                                                     struct winsys_handle *whandle,
-                                                     unsigned *stride);
+    /**
+     * Set a flush callback which is called from winsys when flush is
+     * required.
+     *
+     * \param cs        A command stream to set the callback for.
+     * \param flush     A flush callback function associated with the command stream.
+     * \param user      A user pointer that will be passed to the flush callback.
+     */
+    void (*cs_set_flush)(struct r300_winsys_cs *cs,
+                         void (*flush)(void *),
+                         void *user);
 
-    boolean (*buffer_get_handle)(struct r300_winsys_screen *winsys,
-                                struct r300_winsys_buffer *buffer,
-                                 struct winsys_handle *whandle,
-                                 unsigned stride);
+    /**
+     * Reset the list of buffer objects to validate, usually called
+     * prior to adding buffer objects for validation.
+     *
+     * \param cs        A command stream to reset buffers for.
+     */
+    void (*cs_reset_buffers)(struct r300_winsys_cs *cs);
 
-    boolean (*is_buffer_referenced)(struct r300_winsys_screen *winsys,
-                                    struct r300_winsys_buffer *buffer,
-                                    enum r300_reference_domain domain);
+    /**
+     * Return TRUE if a buffer is referenced by a command stream or by hardware
+     * (i.e. is busy), based on the domain parameter.
+     *
+     * \param cs        A command stream.
+     * \param buf       A winsys buffer.
+     * \param domain    A bitmask of the R300_REF_* enums.
+     */
+    boolean (*cs_is_buffer_referenced)(struct r300_winsys_cs *cs,
+                                       struct r300_winsys_buffer *buf,
+                                       enum r300_reference_domain domain);
 };
 
-struct r300_winsys_screen *
-r300_winsys_screen(struct pipe_screen *screen);
-
 #endif /* R300_WINSYS_H */
index 73cb6a5..a8137d8 100644 (file)
 
 #include "radeon_winsys.h"
 
-#define RADEON_USAGE_DOMAIN_GTT  (1 << 29)
-#define RADEON_USAGE_DOMAIN_VRAM (1 << 30)
-
-#define RADEON_MAX_BOS 24
+#define RADEON_PB_USAGE_VERTEX      (1 << 28)
+#define RADEON_PB_USAGE_DOMAIN_GTT  (1 << 29)
+#define RADEON_PB_USAGE_DOMAIN_VRAM (1 << 30)
 
 static INLINE struct pb_buffer *
 radeon_pb_buffer(struct r300_winsys_buffer *buffer)
@@ -63,24 +62,26 @@ radeon_libdrm_winsys_buffer(struct pb_buffer *buffer)
 struct pb_manager *
 radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws);
 
-boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf,
-                                    enum r300_buffer_domain rd,
-                                     enum r300_buffer_domain wd);
-
+void radeon_drm_bufmgr_add_buffer(struct r300_winsys_cs *cs,
+                                  struct r300_winsys_buffer *buf,
+                                  enum r300_buffer_domain rd,
+                                  enum r300_buffer_domain wd);
 
-void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf,
+void radeon_drm_bufmgr_write_reloc(struct r300_winsys_cs *cs,
+                                   struct r300_winsys_buffer *buf,
                                   enum r300_buffer_domain rd,
-                                   enum r300_buffer_domain wd,
-                                  uint32_t flags);
+                                   enum r300_buffer_domain wd);
 
 struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr,
                                                              uint32_t handle);
 
-void radeon_drm_bufmgr_get_tiling(struct pb_buffer *_buf,
+void radeon_drm_bufmgr_get_tiling(struct r300_winsys_screen *ws,
+                                  struct r300_winsys_buffer *buf,
                                   enum r300_buffer_tiling *microtiled,
                                   enum r300_buffer_tiling *macrotiled);
 
-void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf,
+void radeon_drm_bufmgr_set_tiling(struct r300_winsys_screen *ws,
+                                  struct r300_winsys_buffer *buf,
                                   enum r300_buffer_tiling microtiled,
                                   enum r300_buffer_tiling macrotiled,
                                   uint32_t pitch);
@@ -90,9 +91,19 @@ void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr);
 boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
                                     struct winsys_handle *whandle);
 
-boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf,
+boolean radeon_drm_bufmgr_is_buffer_referenced(struct r300_winsys_cs *cs,
+                                               struct r300_winsys_buffer *buf,
                                                enum r300_reference_domain domain);
 
-void radeon_drm_bufmgr_wait(struct pb_buffer *_buf);
+void radeon_drm_bufmgr_wait(struct r300_winsys_screen *ws,
+                            struct r300_winsys_buffer *buf);
+
+void *radeon_drm_buffer_map(struct r300_winsys_screen *ws,
+                            struct r300_winsys_buffer *buf,
+                            struct r300_winsys_cs *cs,
+                            enum pipe_transfer_usage usage);
+
+void radeon_drm_buffer_unmap(struct r300_winsys_screen *ws,
+                             struct r300_winsys_buffer *buf);
 
 #endif
index c5f133e..5ea5912 100644 (file)
@@ -20,6 +20,9 @@ struct radeon_drm_buffer {
 
     struct radeon_bo *bo;
 
+    /* The CS associated with the last buffer_map. */
+    struct radeon_libdrm_cs *cs;
+
     boolean flinked;
     uint32_t flink;
 
@@ -65,34 +68,53 @@ radeon_drm_buffer_destroy(struct pb_buffer *_buf)
     FREE(buf);
 }
 
+static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage)
+{
+    unsigned res = 0;
+
+    if (usage & PIPE_TRANSFER_READ)
+        res |= PB_USAGE_CPU_READ;
+
+    if (usage & PIPE_TRANSFER_WRITE)
+        res |= PB_USAGE_CPU_WRITE;
+
+    if (usage & PIPE_TRANSFER_DONTBLOCK)
+        res |= PB_USAGE_DONTBLOCK;
+
+    if (usage & PIPE_TRANSFER_UNSYNCHRONIZED)
+        res |= PB_USAGE_UNSYNCHRONIZED;
+
+    return res;
+}
+
 static void *
-radeon_drm_buffer_map(struct pb_buffer *_buf,
+radeon_drm_buffer_map_internal(struct pb_buffer *_buf,
                      unsigned flags)
 {
     struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
+    struct radeon_libdrm_cs *cs = buf->cs;
     int write = 0;
 
-    if (flags & PIPE_TRANSFER_DONTBLOCK) {
-       if ((_buf->base.usage & PIPE_BIND_VERTEX_BUFFER) ||
-           (_buf->base.usage & PIPE_BIND_INDEX_BUFFER))
-           if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs))
+    if (flags & PB_USAGE_DONTBLOCK) {
+        if (_buf->base.usage & RADEON_PB_USAGE_VERTEX)
+            if (cs && radeon_bo_is_referenced_by_cs(buf->bo, cs->cs))
                return NULL;
     }
 
     if (buf->bo->ptr != NULL)
        return buf->bo->ptr;
 
-    if (flags & PIPE_TRANSFER_DONTBLOCK) {
+    if (flags & PB_USAGE_DONTBLOCK) {
         uint32_t domain;
         if (radeon_bo_is_busy(buf->bo, &domain))
             return NULL;
     }
 
-    if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
-        buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data);
+    if (cs && radeon_bo_is_referenced_by_cs(buf->bo, cs->cs)) {
+        cs->flush_cs(cs->flush_data);
     }
 
-    if (flags & PIPE_TRANSFER_WRITE) {
+    if (flags & PB_USAGE_CPU_WRITE) {
         write = 1;
     }
 
@@ -104,7 +126,7 @@ radeon_drm_buffer_map(struct pb_buffer *_buf,
 }
 
 static void
-radeon_drm_buffer_unmap(struct pb_buffer *_buf)
+radeon_drm_buffer_unmap_internal(struct pb_buffer *_buf)
 {
     (void)_buf;
 }
@@ -136,8 +158,8 @@ radeon_drm_buffer_fence(struct pb_buffer *buf,
 
 const struct pb_vtbl radeon_drm_buffer_vtbl = {
     radeon_drm_buffer_destroy,
-    radeon_drm_buffer_map,
-    radeon_drm_buffer_unmap,
+    radeon_drm_buffer_map_internal,
+    radeon_drm_buffer_unmap_internal,
     radeon_drm_buffer_validate,
     radeon_drm_buffer_fence,
     radeon_drm_buffer_get_base_buffer,
@@ -166,7 +188,7 @@ struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager
 
     pipe_reference_init(&buf->base.base.reference, 1);
     buf->base.base.alignment = 0;
-    buf->base.base.usage = PIPE_BIND_SAMPLER_VIEW;
+    buf->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
     buf->base.base.size = 0;
     buf->base.vtbl = &radeon_drm_buffer_vtbl;
     buf->mgr = mgr;
@@ -200,8 +222,8 @@ radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr,
     make_empty_list(buf);
 
     domain =
-        (desc->usage & RADEON_USAGE_DOMAIN_GTT  ? RADEON_GEM_DOMAIN_GTT  : 0) |
-        (desc->usage & RADEON_USAGE_DOMAIN_VRAM ? RADEON_GEM_DOMAIN_VRAM : 0);
+        (desc->usage & RADEON_PB_USAGE_DOMAIN_GTT  ? RADEON_GEM_DOMAIN_GTT  : 0) |
+        (desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ? RADEON_GEM_DOMAIN_VRAM : 0);
 
     buf->bo = radeon_bo_open(rws->bom, 0, size,
                             desc->alignment, domain, 0);
@@ -249,7 +271,8 @@ radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws)
 
 static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
 {
-    struct radeon_drm_buffer *buf;
+    struct radeon_drm_buffer *buf = NULL;
+
     if (_buf->vtbl == &radeon_drm_buffer_vtbl) {
         buf = radeon_drm_buffer(_buf);
     } else {
@@ -257,11 +280,35 @@ static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
        pb_size offset;
        pb_get_base_buffer(_buf, &base_buf, &offset);
 
-       buf = radeon_drm_buffer(base_buf);
+        if (base_buf->vtbl == &radeon_drm_buffer_vtbl)
+            buf = radeon_drm_buffer(base_buf);
     }
+
     return buf;
 }
 
+void *radeon_drm_buffer_map(struct r300_winsys_screen *ws,
+                            struct r300_winsys_buffer *buf,
+                            struct r300_winsys_cs *cs,
+                            enum pipe_transfer_usage usage)
+{
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
+    struct radeon_drm_buffer *rbuf = get_drm_buffer(_buf);
+
+    if (rbuf)
+        rbuf->cs = radeon_libdrm_cs(cs);
+
+    return pb_map(_buf, get_pb_usage_from_transfer_flags(usage));
+}
+
+void radeon_drm_buffer_unmap(struct r300_winsys_screen *ws,
+                             struct r300_winsys_buffer *buf)
+{
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
+
+    pb_unmap(_buf);
+}
+
 boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
                                     struct winsys_handle *whandle)
 {
@@ -286,11 +333,12 @@ boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
     return TRUE;
 }
 
-void radeon_drm_bufmgr_get_tiling(struct pb_buffer *_buf,
+void radeon_drm_bufmgr_get_tiling(struct r300_winsys_screen *ws,
+                                  struct r300_winsys_buffer *_buf,
                                   enum r300_buffer_tiling *microtiled,
                                   enum r300_buffer_tiling *macrotiled)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
     uint32_t flags = 0, pitch;
 
     radeon_bo_get_tiling(buf->bo, &flags, &pitch);
@@ -304,12 +352,13 @@ void radeon_drm_bufmgr_get_tiling(struct pb_buffer *_buf,
        *macrotiled = R300_BUFFER_TILED;
 }
 
-void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf,
+void radeon_drm_bufmgr_set_tiling(struct r300_winsys_screen *ws,
+                                  struct r300_winsys_buffer *_buf,
                                   enum r300_buffer_tiling microtiled,
                                   enum r300_buffer_tiling macrotiled,
                                   uint32_t pitch)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
     uint32_t flags = 0;
     if (microtiled == R300_BUFFER_TILED)
         flags |= RADEON_BO_FLAGS_MICRO_TILE;
@@ -324,56 +373,60 @@ void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf,
     radeon_bo_set_tiling(buf->bo, flags, pitch);
 }
 
-static uint32_t gem_domain(enum r300_buffer_domain dom)
+static uint32_t get_gem_domain(enum r300_buffer_domain domain)
 {
     uint32_t res = 0;
 
-    if (dom & R300_DOMAIN_GTT)
+    if (domain & R300_DOMAIN_GTT)
         res |= RADEON_GEM_DOMAIN_GTT;
-    if (dom & R300_DOMAIN_VRAM)
+    if (domain & R300_DOMAIN_VRAM)
         res |= RADEON_GEM_DOMAIN_VRAM;
     return res;
 }
 
-boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf,
-                                    enum r300_buffer_domain rd,
-                                     enum r300_buffer_domain wd)
+void radeon_drm_bufmgr_add_buffer(struct r300_winsys_cs *rcs,
+                                  struct r300_winsys_buffer *_buf,
+                                  enum r300_buffer_domain rd,
+                                  enum r300_buffer_domain wd)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
-    uint32_t gem_rd = gem_domain(rd);
-    uint32_t gem_wd = gem_domain(wd);
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
+    uint32_t gem_rd = get_gem_domain(rd);
+    uint32_t gem_wd = get_gem_domain(wd);
 
-    radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo,
-                                         gem_rd, gem_wd);
-    return TRUE;
+    radeon_cs_space_add_persistent_bo(cs->cs, buf->bo, gem_rd, gem_wd);
 }
 
-void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf,
+void radeon_drm_bufmgr_write_reloc(struct r300_winsys_cs *rcs,
+                                   struct r300_winsys_buffer *_buf,
                                   enum r300_buffer_domain rd,
-                                   enum r300_buffer_domain wd,
-                                  uint32_t flags)
+                                   enum r300_buffer_domain wd)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
     int retval;
-    uint32_t gem_rd = gem_domain(rd);
-    uint32_t gem_wd = gem_domain(wd);
+    uint32_t gem_rd = get_gem_domain(rd);
+    uint32_t gem_wd = get_gem_domain(wd);
 
-    retval = radeon_cs_write_reloc(buf->mgr->rws->cs,
-                                  buf->bo, gem_rd, gem_wd, flags);
+    cs->cs->cdw = cs->base.cdw;
+    retval = radeon_cs_write_reloc(cs->cs, buf->bo, gem_rd, gem_wd, 0);
+    cs->base.cdw = cs->cs->cdw;
     if (retval) {
         fprintf(stderr, "radeon: Relocation of %p (%d, %d, %d) failed!\n",
-                buf, gem_rd, gem_wd, flags);
+                buf, gem_rd, gem_wd, 0);
     }
 }
 
-boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf,
+boolean radeon_drm_bufmgr_is_buffer_referenced(struct r300_winsys_cs *rcs,
+                                               struct r300_winsys_buffer *_buf,
                                                enum r300_reference_domain domain)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
     uint32_t tmp;
 
     if (domain & R300_REF_CS) {
-        if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
+        if (radeon_bo_is_referenced_by_cs(buf->bo, cs->cs)) {
             return TRUE;
         }
     }
@@ -387,7 +440,6 @@ boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf,
     return FALSE;
 }
 
-
 void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
 {
     struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
@@ -402,9 +454,10 @@ void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
     make_empty_list(&mgr->buffer_map_list);
 }
 
-void radeon_drm_bufmgr_wait(struct pb_buffer *_buf)
+void radeon_drm_bufmgr_wait(struct r300_winsys_screen *ws,
+                            struct r300_winsys_buffer *_buf)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
 
     radeon_bo_wait(buf->bo);
 }
index af35497..4e89c07 100644 (file)
 #include "radeon_cs_gem.h"
 #include "state_tracker/drm_driver.h"
 
+#include "util/u_memory.h"
+
+static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage,
+                                               enum r300_buffer_domain domain)
+{
+    unsigned res = 0;
+
+    if (bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET |
+                PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT))
+        res |= PB_USAGE_GPU_WRITE;
+
+    if (bind & PIPE_BIND_SAMPLER_VIEW)
+        res |= PB_USAGE_GPU_READ | PB_USAGE_GPU_WRITE;
+
+    if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
+        res |= PB_USAGE_GPU_READ;
+
+    if (bind & PIPE_BIND_TRANSFER_WRITE)
+        res |= PB_USAGE_CPU_WRITE;
+
+    if (bind & PIPE_BIND_TRANSFER_READ)
+        res |= PB_USAGE_CPU_READ;
+
+    /* Is usage of any use for us? Probably not. */
+
+    /* Now add driver-specific usage flags. */
+    if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
+        res |= RADEON_PB_USAGE_VERTEX;
+
+    if (domain & R300_DOMAIN_GTT)
+        res |= RADEON_PB_USAGE_DOMAIN_GTT;
+
+    if (domain & R300_DOMAIN_VRAM)
+        res |= RADEON_PB_USAGE_DOMAIN_VRAM;
+
+    return res;
+}
+
 static struct r300_winsys_buffer *
 radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws,
-                                unsigned alignment,
-                                unsigned usage,
-                                 enum r300_buffer_domain domain,
-                                unsigned size)
+                                 unsigned size,
+                                 unsigned alignment,
+                                 unsigned bind,
+                                 unsigned usage,
+                                 enum r300_buffer_domain domain)
 {
-    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    struct radeon_libdrm_winsys *ws = radeon_libdrm_winsys(rws);
     struct pb_desc desc;
     struct pb_manager *provider;
     struct pb_buffer *buffer;
 
-    /* XXX this is hackish, but it's the only way to pass these flags
-     * to the real create function. */
-    usage &= ~(RADEON_USAGE_DOMAIN_GTT | RADEON_USAGE_DOMAIN_VRAM);
-    if (domain & R300_DOMAIN_GTT)
-        usage |= RADEON_USAGE_DOMAIN_GTT;
-    if (domain & R300_DOMAIN_VRAM)
-        usage |= RADEON_USAGE_DOMAIN_VRAM;
-
     memset(&desc, 0, sizeof(desc));
     desc.alignment = alignment;
-    desc.usage = usage;
+    desc.usage = get_pb_usage_from_create_flags(bind, usage, domain);
 
-    if (usage & PIPE_BIND_CONSTANT_BUFFER)
+    /* Assign a buffer manager. */
+    if (bind & PIPE_BIND_CONSTANT_BUFFER)
         provider = ws->mman;
-    else if ((usage & PIPE_BIND_VERTEX_BUFFER) ||
-            (usage & PIPE_BIND_INDEX_BUFFER))
+    else if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
        provider = ws->cman;
     else
         provider = ws->kman;
+
     buffer = provider->create_buffer(provider, size, &desc);
     if (!buffer)
        return NULL;
@@ -65,55 +97,6 @@ radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws,
     return radeon_libdrm_winsys_buffer(buffer);
 }
 
-static void radeon_r300_winsys_buffer_destroy(struct r300_winsys_buffer *buf)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-
-    pb_destroy(_buf);
-}
-static void radeon_r300_winsys_buffer_set_tiling(struct r300_winsys_screen *rws,
-                                                 struct r300_winsys_buffer *buf,
-                                                 uint32_t pitch,
-                                                 enum r300_buffer_tiling microtiled,
-                                                 enum r300_buffer_tiling macrotiled)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-    radeon_drm_bufmgr_set_tiling(_buf, microtiled, macrotiled, pitch);
-}
-
-static void radeon_r300_winsys_buffer_get_tiling(struct r300_winsys_screen *rws,
-                                                 struct r300_winsys_buffer *buf,
-                                                 enum r300_buffer_tiling *microtiled,
-                                                 enum r300_buffer_tiling *macrotiled)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-    radeon_drm_bufmgr_get_tiling(_buf, microtiled, macrotiled);
-}
-
-static void *radeon_r300_winsys_buffer_map(struct r300_winsys_screen *ws,
-                                          struct r300_winsys_buffer *buf,
-                                          unsigned usage)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-
-    return pb_map(_buf, usage);
-}
-
-static void radeon_r300_winsys_buffer_unmap(struct r300_winsys_screen *ws,
-                                           struct r300_winsys_buffer *buf)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-
-    pb_unmap(_buf);
-}
-
-static void radeon_r300_winsys_buffer_wait(struct r300_winsys_screen *ws,
-                                           struct r300_winsys_buffer *buf)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-    radeon_drm_bufmgr_wait(_buf);
-}
-
 static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
                                                struct r300_winsys_buffer **pdst,
                                                struct r300_winsys_buffer *src)
@@ -126,20 +109,11 @@ static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
     *pdst = radeon_libdrm_winsys_buffer(_dst);
 }
 
-static boolean radeon_r300_winsys_is_buffer_referenced(struct r300_winsys_screen *rws,
-                                                      struct r300_winsys_buffer *buf,
-                                                       enum r300_reference_domain domain)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-
-    return radeon_drm_bufmgr_is_buffer_referenced(_buf, domain);
-}
-
 static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws,
                                                                         struct winsys_handle *whandle,
                                                                         unsigned *stride)
 {
-    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    struct radeon_libdrm_winsys *ws = radeon_libdrm_winsys(rws);
     struct pb_buffer *_buf;
 
     *stride = whandle->stride;
@@ -150,111 +124,57 @@ static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r
 
 static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws,
                                                    struct r300_winsys_buffer *buffer,
-                                                    struct winsys_handle *whandle,
-                                                    unsigned stride)
+                                                    unsigned stride,
+                                                    struct winsys_handle *whandle)
 {
     struct pb_buffer *_buf = radeon_pb_buffer(buffer);
     whandle->stride = stride;
     return radeon_drm_bufmgr_get_handle(_buf, whandle);
 }
 
-static void radeon_set_flush_cb(struct r300_winsys_screen *rws,
-                                void (*flush_cb)(void *),
-                                void *data)
-{
-    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
-    ws->flush_cb = flush_cb;
-    ws->flush_data = data;
-    radeon_cs_space_set_flush(ws->cs, flush_cb, data);
-}
-
-static boolean radeon_add_buffer(struct r300_winsys_screen *rws,
-                                 struct r300_winsys_buffer *buf,
-                                 enum r300_buffer_domain rd,
-                                 enum r300_buffer_domain wd)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-
-    return radeon_drm_bufmgr_add_buffer(_buf, rd, wd);
-}
-
-static boolean radeon_validate(struct r300_winsys_screen *rws)
+static void radeon_r300_winsys_cs_set_flush(struct r300_winsys_cs *rcs,
+                                            void (*flush)(void *),
+                                            void *user)
 {
-    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
-    if (radeon_cs_space_check(ws->cs) < 0) {
-        return FALSE;
-    }
-
-    /* Things are fine, we can proceed as normal. */
-    return TRUE;
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
+    cs->flush_cs = flush;
+    cs->flush_data = user;
+    radeon_cs_space_set_flush(cs->cs, flush, user);
 }
 
-static unsigned radeon_get_cs_free_dwords(struct r300_winsys_screen *rws)
+static boolean radeon_r300_winsys_cs_validate(struct r300_winsys_cs *rcs)
 {
-    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
-    struct radeon_cs *cs = ws->cs;
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
 
-    return cs->ndw - cs->cdw;
+    return radeon_cs_space_check(cs->cs) >= 0;
 }
 
-static uint32_t *radeon_get_cs_pointer(struct r300_winsys_screen *rws,
-                                       unsigned count)
+static void radeon_r300_winsys_cs_reset_buffers(struct r300_winsys_cs *rcs)
 {
-    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
-    struct radeon_cs *cs = ws->cs;
-    uint32_t *ptr = cs->packets + cs->cdw;
-
-    cs->cdw += count;
-    return ptr;
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
+    radeon_cs_space_reset_bos(cs->cs);
 }
 
-static void radeon_write_cs_dword(struct r300_winsys_screen *rws,
-                                  uint32_t dword)
+static void radeon_r300_winsys_cs_flush(struct r300_winsys_cs *rcs)
 {
-    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
-    radeon_cs_write_dword(ws->cs, dword);
-}
-
-static void radeon_write_cs_table(struct r300_winsys_screen *rws,
-                                  const void *table, unsigned count)
-{
-    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
-    radeon_cs_write_table(ws->cs, table, count);
-}
-
-static void radeon_write_cs_reloc(struct r300_winsys_screen *rws,
-                                  struct r300_winsys_buffer *buf,
-                                  enum r300_buffer_domain rd,
-                                  enum r300_buffer_domain wd,
-                                  uint32_t flags)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-    radeon_drm_bufmgr_write_reloc(_buf, rd, wd, flags);
-}
-
-static void radeon_reset_bos(struct r300_winsys_screen *rws)
-{
-    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
-    radeon_cs_space_reset_bos(ws->cs);
-}
-
-static void radeon_flush_cs(struct r300_winsys_screen *rws)
-{
-    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
     int retval;
 
     /* Don't flush a zero-sized CS. */
-    if (!ws->cs->cdw) {
+    if (!cs->base.cdw) {
         return;
     }
 
-    radeon_drm_bufmgr_flush_maps(ws->kman);
+    cs->cs->cdw = cs->base.cdw;
+
+    radeon_drm_bufmgr_flush_maps(cs->ws->kman);
+
     /* Emit the CS. */
-    retval = radeon_cs_emit(ws->cs);
+    retval = radeon_cs_emit(cs->cs);
     if (retval) {
         if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) {
             fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n");
-            radeon_cs_print(ws->cs, stderr);
+            radeon_cs_print(cs->cs, stderr);
         } else {
             fprintf(stderr, "radeon: The kernel rejected CS, "
                             "see dmesg for more information.\n");
@@ -265,11 +185,15 @@ static void radeon_flush_cs(struct r300_winsys_screen *rws)
      * Someday, when we care about performance, we should really find a way
      * to rotate between two or three CS objects so that the GPU can be
      * spinning through one CS while another one is being filled. */
-    radeon_cs_erase(ws->cs);
+    radeon_cs_erase(cs->cs);
+
+    cs->base.ptr = cs->cs->packets;
+    cs->base.cdw = cs->cs->cdw;
+    cs->base.ndw = cs->cs->ndw;
 }
 
 static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
-                            enum r300_value_id id)
+                                 enum r300_value_id id)
 {
     struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws;
 
@@ -288,11 +212,42 @@ static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
     return 0;
 }
 
-static void
-radeon_winsys_destroy(struct r300_winsys_screen *rws)
+static struct r300_winsys_cs *radeon_r300_winsys_cs_create(struct r300_winsys_screen *rws)
+{
+    struct radeon_libdrm_winsys *ws = radeon_libdrm_winsys(rws);
+    struct radeon_libdrm_cs *cs = CALLOC_STRUCT(radeon_libdrm_cs);
+
+    if (!cs)
+        return NULL;
+
+    /* Size limit on IBs is 64 kibibytes. */
+    cs->cs = radeon_cs_create(ws->csm, 1024 * 64 / 4);
+    if (!cs->cs) {
+        FREE(cs);
+        return NULL;
+    }
+
+    radeon_cs_set_limit(cs->cs,
+            RADEON_GEM_DOMAIN_GTT, ws->gart_size);
+    radeon_cs_set_limit(cs->cs,
+            RADEON_GEM_DOMAIN_VRAM, ws->vram_size);
+
+    cs->ws = ws;
+    cs->base.ptr = cs->cs->packets;
+    cs->base.cdw = cs->cs->cdw;
+    cs->base.ndw = cs->cs->ndw;
+    return &cs->base;
+}
+
+static void radeon_r300_winsys_cs_destroy(struct r300_winsys_cs *rcs)
+{
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
+    radeon_cs_destroy(cs->cs);
+}
+
+static void radeon_winsys_destroy(struct r300_winsys_screen *rws)
 {
     struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws;
-    radeon_cs_destroy(ws->cs);
 
     ws->cman->destroy(ws->cman);
     ws->kman->destroy(ws->kman);
@@ -302,10 +257,8 @@ radeon_winsys_destroy(struct r300_winsys_screen *rws)
     radeon_cs_manager_gem_dtor(ws->csm);
 }
 
-boolean
-radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws)
+boolean radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws)
 {
-    
     ws->csm = radeon_cs_manager_gem_ctor(fd);
     if (!ws->csm)
        goto fail;
@@ -324,39 +277,28 @@ radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws)
     if (!ws->mman)
        goto fail;
 
-    /* Size limit on IBs is 64 kibibytes. */
-    ws->cs = radeon_cs_create(ws->csm, 1024 * 64 / 4);
-    if (!ws->cs)
-       goto fail;
-    radeon_cs_set_limit(ws->cs,
-            RADEON_GEM_DOMAIN_GTT, ws->gart_size);
-    radeon_cs_set_limit(ws->cs,
-            RADEON_GEM_DOMAIN_VRAM, ws->vram_size);
-
-    ws->base.add_buffer = radeon_add_buffer;
-    ws->base.validate = radeon_validate;
     ws->base.destroy = radeon_winsys_destroy;
-    ws->base.get_cs_free_dwords = radeon_get_cs_free_dwords;
-    ws->base.get_cs_pointer = radeon_get_cs_pointer;
-    ws->base.write_cs_dword = radeon_write_cs_dword;
-    ws->base.write_cs_table = radeon_write_cs_table;
-    ws->base.write_cs_reloc = radeon_write_cs_reloc;
-    ws->base.flush_cs = radeon_flush_cs;
-    ws->base.reset_bos = radeon_reset_bos;
-    ws->base.set_flush_cb = radeon_set_flush_cb;
     ws->base.get_value = radeon_get_value;
 
     ws->base.buffer_create = radeon_r300_winsys_buffer_create;
-    ws->base.buffer_destroy = radeon_r300_winsys_buffer_destroy;
-    ws->base.buffer_set_tiling = radeon_r300_winsys_buffer_set_tiling;
-    ws->base.buffer_get_tiling = radeon_r300_winsys_buffer_get_tiling;
-    ws->base.buffer_map = radeon_r300_winsys_buffer_map;
-    ws->base.buffer_unmap = radeon_r300_winsys_buffer_unmap;
-    ws->base.buffer_wait = radeon_r300_winsys_buffer_wait;
+    ws->base.buffer_set_tiling = radeon_drm_bufmgr_set_tiling;
+    ws->base.buffer_get_tiling = radeon_drm_bufmgr_get_tiling;
+    ws->base.buffer_map = radeon_drm_buffer_map;
+    ws->base.buffer_unmap = radeon_drm_buffer_unmap;
+    ws->base.buffer_wait = radeon_drm_bufmgr_wait;
     ws->base.buffer_reference = radeon_r300_winsys_buffer_reference;
     ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle;
     ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle;
-    ws->base.is_buffer_referenced = radeon_r300_winsys_is_buffer_referenced;
+
+    ws->base.cs_create = radeon_r300_winsys_cs_create;
+    ws->base.cs_destroy = radeon_r300_winsys_cs_destroy;
+    ws->base.cs_add_buffer = radeon_drm_bufmgr_add_buffer;
+    ws->base.cs_validate = radeon_r300_winsys_cs_validate;
+    ws->base.cs_write_reloc = radeon_drm_bufmgr_write_reloc;
+    ws->base.cs_flush = radeon_r300_winsys_cs_flush;
+    ws->base.cs_reset_buffers = radeon_r300_winsys_cs_reset_buffers;
+    ws->base.cs_set_flush = radeon_r300_winsys_cs_set_flush;
+    ws->base.cs_is_buffer_referenced = radeon_drm_bufmgr_is_buffer_referenced;
     return TRUE;
 
 fail:
@@ -373,7 +315,5 @@ fail:
     if (ws->mman)
        ws->mman->destroy(ws->mman);
 
-    if (ws->cs)
-       radeon_cs_destroy(ws->cs);
     return FALSE;
 }
index ca789be..9a25e76 100644 (file)
@@ -75,19 +75,32 @@ struct radeon_libdrm_winsys {
 
     /* Radeon CS manager. */
     struct radeon_cs_manager *csm;
+};
+
+struct radeon_libdrm_cs {
+    struct r300_winsys_cs base;
+
+    /* The winsys. */
+    struct radeon_libdrm_winsys *ws;
 
-    /* Current CS. */
+    /* The libdrm command stream. */
     struct radeon_cs *cs;
 
-    /* Flush CB */
-    void (*flush_cb)(void *);
+    /* Flush CS. */
+    void (*flush_cs)(void *);
     void *flush_data;
 };
 
+static INLINE struct radeon_libdrm_cs *
+radeon_libdrm_cs(struct r300_winsys_cs *base)
+{
+    return (struct radeon_libdrm_cs*)base;
+}
+
 static INLINE struct radeon_libdrm_winsys *
-radeon_winsys_screen(struct r300_winsys_screen *base)
+radeon_libdrm_winsys(struct r300_winsys_screen *base)
 {
-  return (struct radeon_libdrm_winsys *)base;
+    return (struct radeon_libdrm_winsys*)base;
 }
 
 #endif