diff options
Diffstat (limited to 'src/gallium/drivers')
132 files changed, 5646 insertions, 2555 deletions
diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c index 49cece58b8f..411f204f15a 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.c +++ b/src/gallium/drivers/cell/ppu/cell_context.c @@ -73,7 +73,7 @@ cell_destroy_context( struct pipe_context *pipe ) static struct draw_context * cell_draw_create(struct cell_context *cell) { - struct draw_context *draw = draw_create(); + struct draw_context *draw = draw_create(&cell->pipe); #if 0 /* broken */ if (getenv("GALLIUM_CELL_VS")) { diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c index b50a30bee80..6a1e4d8a646 100644 --- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c +++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c @@ -103,7 +103,7 @@ cell_draw_range_elements(struct pipe_context *pipe, draw_set_mapped_vertex_buffer(draw, i, NULL); } if (indexBuffer) { - draw_set_mapped_element_buffer(draw, 0, NULL); + draw_set_mapped_element_buffer(draw, 0, 0, NULL); } /* @@ -122,7 +122,7 @@ cell_draw_elements(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { cell_draw_range_elements( pipe, indexBuffer, - indexSize, indeBias, + indexSize, indexBias, 0, 0xffffffff, mode, start, count ); } diff --git a/src/gallium/drivers/cell/ppu/cell_fence.c b/src/gallium/drivers/cell/ppu/cell_fence.c index eac798e8cf6..34ca864155b 100644 --- a/src/gallium/drivers/cell/ppu/cell_fence.c +++ b/src/gallium/drivers/cell/ppu/cell_fence.c @@ -123,7 +123,7 @@ cell_free_fenced_buffers(struct cell_context *cell, while (node) { struct cell_buffer_node *next = node->next; assert(node->buffer); - pipe_buffer_unmap(ps, node->buffer); + /* XXX need this? pipe_buffer_unmap(ps, node->buffer);*/ #if 0 printf("Unref buffer %p\n", node->buffer); if (node->buffer->reference.count == 1) diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c index ecc9de4df66..03f84d295b5 100644 --- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c @@ -204,7 +204,7 @@ cell_bind_rasterizer_state(struct pipe_context *pipe, void *rast) struct cell_context *cell = cell_context(pipe); /* pass-through to draw module */ - draw_set_rasterizer_state(cell->draw, rasterizer); + draw_set_rasterizer_state(cell->draw, rasterizer, rast); cell->rasterizer = rasterizer; diff --git a/src/gallium/drivers/cell/ppu/cell_render.c b/src/gallium/drivers/cell/ppu/cell_render.c index 79cb8df82fa..f648482c551 100644 --- a/src/gallium/drivers/cell/ppu/cell_render.c +++ b/src/gallium/drivers/cell/ppu/cell_render.c @@ -152,7 +152,7 @@ cell_flush_prim_buffer(struct cell_context *cell) struct cell_command_render *render = &cell_global.command[i].render; render->prim_type = PIPE_PRIM_TRIANGLES; render->num_verts = cell->prim_buffer.num_verts; - render->front_winding = cell->rasterizer->front_winding; + render->front_ccw = cell->rasterizer->front_ccw; render->vertex_size = cell->vertex_info->size * 4; render->xmin = cell->prim_buffer.xmin; render->ymin = cell->prim_buffer.ymin; diff --git a/src/gallium/drivers/cell/ppu/cell_screen.c b/src/gallium/drivers/cell/ppu/cell_screen.c index 9bb3abfc9dd..0f12e0667eb 100644 --- a/src/gallium/drivers/cell/ppu/cell_screen.c +++ b/src/gallium/drivers/cell/ppu/cell_screen.c @@ -55,7 +55,7 @@ cell_get_name(struct pipe_screen *screen) static int -cell_get_param(struct pipe_screen *screen, int param) +cell_get_param(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: @@ -76,6 +76,8 @@ cell_get_param(struct pipe_screen *screen, int param) return 1; case PIPE_CAP_OCCLUSION_QUERY: return 1; + case PIPE_CAP_TIMER_QUERY: + return 0; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 10; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: @@ -105,7 +107,7 @@ cell_get_param(struct pipe_screen *screen, int param) static float -cell_get_paramf(struct pipe_screen *screen, int param) +cell_get_paramf(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index d08334d892b..b3042df7792 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -34,7 +34,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" - +#include "util/u_transfer.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -42,7 +42,7 @@ #include "cell_context.h" #include "cell_screen.h" #include "cell_state.h" -#include "cell_resource.h" +#include "cell_texture.h" #include "state_tracker/sw_winsys.h" @@ -155,9 +155,9 @@ fail: static void -cell_resource_destroy(struct pipe_resource *pt) +cell_resource_destroy(struct pipe_screen *scrn, struct pipe_resource *pt) { - struct cell_screen *screen = cell_screen(pt->screen); + struct cell_screen *screen = cell_screen(scrn); struct sw_winsys *winsys = screen->winsys; struct cell_resource *ct = cell_resource(pt); @@ -365,10 +365,10 @@ cell_get_transfer(struct pipe_context *ctx, { struct cell_resource *ct = cell_resource(resource); struct cell_transfer *ctrans; - enum pipe_format *format = resource->format; + enum pipe_format format = resource->format; assert(resource); - assert(level <= resource->last_level); + assert(sr.level <= resource->last_level); /* make sure the requested region is in the image bounds */ assert(box->x + box->width <= u_minify(resource->width0, sr.level)); @@ -612,6 +612,24 @@ cell_user_buffer_create(struct pipe_screen *screen, } +static struct pipe_resource * +cell_resource_from_handle(struct pipe_screen *screen, + const struct pipe_resource *templat, + struct winsys_handle *handle) +{ + /* XXX todo */ + return NULL; +} + + +static boolean +cell_resource_get_handle(struct pipe_screen *scree, + struct pipe_resource *tex, + struct winsys_handle *handle) +{ + /* XXX todo */ + return FALSE; +} void @@ -630,7 +648,7 @@ cell_init_screen_texture_funcs(struct pipe_screen *screen) } void -cell_init_transfer_funcs(struct cell_context *cell) +cell_init_texture_transfer_funcs(struct cell_context *cell) { cell->pipe.get_transfer = cell_get_transfer; cell->pipe.transfer_destroy = cell_transfer_destroy; diff --git a/src/gallium/drivers/cell/ppu/cell_vbuf.c b/src/gallium/drivers/cell/ppu/cell_vbuf.c index cfaffb52a85..37b71956482 100644 --- a/src/gallium/drivers/cell/ppu/cell_vbuf.c +++ b/src/gallium/drivers/cell/ppu/cell_vbuf.c @@ -165,9 +165,9 @@ cell_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim) static void -cell_vbuf_draw(struct vbuf_render *vbr, - const ushort *indices, - uint nr_indices) +cell_vbuf_draw_elements(struct vbuf_render *vbr, + const ushort *indices, + uint nr_indices) { struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr); struct cell_context *cell = cvbr->cell; @@ -319,7 +319,7 @@ cell_init_vbuf(struct cell_context *cell) cell->vbuf_render->base.map_vertices = cell_vbuf_map_vertices; cell->vbuf_render->base.unmap_vertices = cell_vbuf_unmap_vertices; cell->vbuf_render->base.set_primitive = cell_vbuf_set_primitive; - cell->vbuf_render->base.draw = cell_vbuf_draw; + cell->vbuf_render->base.draw_elements = cell_vbuf_draw_elements; cell->vbuf_render->base.release_vertices = cell_vbuf_release_vertices; cell->vbuf_render->base.destroy = cell_vbuf_destroy; diff --git a/src/gallium/drivers/cell/spu/spu_tri.c b/src/gallium/drivers/cell/spu/spu_tri.c index f619380d807..efeebca27bb 100644 --- a/src/gallium/drivers/cell/spu/spu_tri.c +++ b/src/gallium/drivers/cell/spu/spu_tri.c @@ -568,7 +568,7 @@ setup_sort_vertices(const qword vs) ASSERT(CELL_FACING_FRONT == 0); ASSERT(CELL_FACING_BACK == 1); setup.facing = (area * sign > 0.0f) - ^ (spu.rasterizer.front_winding == PIPE_WINDING_CW); + ^ (!spu.rasterizer.front_ccw); return TRUE; } diff --git a/src/gallium/drivers/i915/i915_prim_vbuf.c b/src/gallium/drivers/i915/i915_prim_vbuf.c index df9e68af4fc..f8665acbe18 100644 --- a/src/gallium/drivers/i915/i915_prim_vbuf.c +++ b/src/gallium/drivers/i915/i915_prim_vbuf.c @@ -544,9 +544,9 @@ draw_calc_nr_indices(uint nr_indices, unsigned type) } static void -i915_vbuf_render_draw(struct vbuf_render *render, - const ushort *indices, - uint nr_indices) +i915_vbuf_render_draw_elements(struct vbuf_render *render, + const ushort *indices, + uint nr_indices) { struct i915_vbuf_render *i915_render = i915_vbuf_render(render); struct i915_context *i915 = i915_render->i915; @@ -638,7 +638,7 @@ i915_vbuf_render_create(struct i915_context *i915) i915_render->base.map_vertices = i915_vbuf_render_map_vertices; i915_render->base.unmap_vertices = i915_vbuf_render_unmap_vertices; i915_render->base.set_primitive = i915_vbuf_render_set_primitive; - i915_render->base.draw = i915_vbuf_render_draw; + i915_render->base.draw_elements = i915_vbuf_render_draw_elements; i915_render->base.draw_arrays = i915_vbuf_render_draw_arrays; i915_render->base.release_vertices = i915_vbuf_render_release_vertices; i915_render->base.destroy = i915_vbuf_render_destroy; diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index c10ba25d2d5..0897a863dbd 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -90,7 +90,7 @@ i915_get_name(struct pipe_screen *screen) } static int -i915_get_param(struct pipe_screen *screen, int param) +i915_get_param(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: @@ -113,6 +113,8 @@ i915_get_param(struct pipe_screen *screen, int param) return 1; case PIPE_CAP_OCCLUSION_QUERY: return 0; + case PIPE_CAP_TIMER_QUERY: + return 0; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: @@ -133,7 +135,7 @@ i915_get_param(struct pipe_screen *screen, int param) } static float -i915_get_paramf(struct pipe_screen *screen, int param) +i915_get_paramf(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index e008195a910..e767aa9f8f0 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -686,17 +686,23 @@ i915_create_rasterizer_state(struct pipe_context *pipe, else cso->sc[0] = _3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT; - switch (rasterizer->cull_mode) { - case PIPE_WINDING_NONE: + switch (rasterizer->cull_face) { + case PIPE_FACE_NONE: cso->LIS4 |= S4_CULLMODE_NONE; break; - case PIPE_WINDING_CW: - cso->LIS4 |= S4_CULLMODE_CW; + case PIPE_FACE_FRONT: + if (rasterizer->front_ccw) + cso->LIS4 |= S4_CULLMODE_CCW; + else + cso->LIS4 |= S4_CULLMODE_CW; break; - case PIPE_WINDING_CCW: - cso->LIS4 |= S4_CULLMODE_CCW; + case PIPE_FACE_BACK: + if (rasterizer->front_ccw) + cso->LIS4 |= S4_CULLMODE_CW; + else + cso->LIS4 |= S4_CULLMODE_CCW; break; - case PIPE_WINDING_BOTH: + case PIPE_FACE_FRONT_AND_BACK: cso->LIS4 |= S4_CULLMODE_BOTH; break; } diff --git a/src/gallium/drivers/i965/SConscript b/src/gallium/drivers/i965/SConscript index 85c4d7ed22e..019af682f68 100644 --- a/src/gallium/drivers/i965/SConscript +++ b/src/gallium/drivers/i965/SConscript @@ -50,7 +50,7 @@ i965 = env.ConvenienceLibrary( 'brw_sf_state.c', 'brw_state_batch.c', 'brw_state_cache.c', -# 'brw_state_debug.c', + 'brw_state_debug.c', 'brw_state_upload.c', 'brw_swtnl.c', 'brw_urb.c', diff --git a/src/gallium/drivers/i965/brw_batchbuffer.c b/src/gallium/drivers/i965/brw_batchbuffer.c index 003b1fd5bf0..8b3f46f2c16 100644 --- a/src/gallium/drivers/i965/brw_batchbuffer.c +++ b/src/gallium/drivers/i965/brw_batchbuffer.c @@ -161,7 +161,7 @@ brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch, int ret; if (batch->ptr - batch->map > batch->buf->size) { - debug_printf("bad relocation ptr %p map %p offset %d size %d\n", + debug_printf("bad relocation ptr %p map %p offset %li size %i\n", batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size); return PIPE_ERROR_OUT_OF_MEMORY; diff --git a/src/gallium/drivers/i965/brw_pipe_rast.c b/src/gallium/drivers/i965/brw_pipe_rast.c index 2117e91a9e4..4c1a6d7dcdf 100644 --- a/src/gallium/drivers/i965/brw_pipe_rast.c +++ b/src/gallium/drivers/i965/brw_pipe_rast.c @@ -42,7 +42,7 @@ calculate_clip_key_rast( const struct brw_context *brw, key->do_flat_shading = templ->flatshade; - if (templ->cull_mode == PIPE_WINDING_BOTH) { + if (templ->cull_face == PIPE_FACE_FRONT_AND_BACK) { key->clip_mode = BRW_CLIPMODE_REJECT_ALL; return; } @@ -50,12 +50,18 @@ calculate_clip_key_rast( const struct brw_context *brw, key->fill_ccw = CLIP_CULL; key->fill_cw = CLIP_CULL; - if (!(templ->cull_mode & PIPE_WINDING_CCW)) { - key->fill_ccw = translate_fill(templ->fill_ccw); + if (!(templ->cull_face & PIPE_FACE_FRONT)) { + if (templ->front_ccw) + key->fill_ccw = translate_fill(templ->fill_front); + else + key->fill_cw = translate_fill(templ->fill_front); } - if (!(templ->cull_mode & PIPE_WINDING_CW)) { - key->fill_cw = translate_fill(templ->fill_cw); + if (!(templ->cull_face & PIPE_FACE_BACK)) { + if (templ->front_ccw) + key->fill_cw = translate_fill(templ->fill_back); + else + key->fill_ccw = translate_fill(templ->fill_back); } if (key->fill_cw == CLIP_LINE || @@ -66,8 +72,29 @@ calculate_clip_key_rast( const struct brw_context *brw, key->clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED; } - key->offset_ccw = templ->offset_ccw; - key->offset_cw = templ->offset_cw; + switch (key->fill_cw) { + case CLIP_POINT: + key->offset_cw = templ->offset_point; + break; + case CLIP_LINE: + key->offset_cw = templ->offset_line; + break; + case CLIP_FILL: + key->offset_cw = templ->offset_tri; + break; + } + + switch (key->fill_ccw) { + case CLIP_POINT: + key->offset_ccw = templ->offset_point; + break; + case CLIP_LINE: + key->offset_ccw = templ->offset_line; + break; + case CLIP_FILL: + key->offset_ccw = templ->offset_tri; + break; + } if (templ->light_twoside && key->fill_cw != CLIP_CULL) key->copy_bfc_cw = 1; @@ -111,12 +138,12 @@ static void *brw_create_rasterizer_state( struct pipe_context *pipe, /* Caclculate lookup value for WM IZ table. */ if (templ->line_smooth) { - if (templ->fill_cw == PIPE_POLYGON_MODE_LINE && - templ->fill_ccw == PIPE_POLYGON_MODE_LINE) { + if (templ->fill_front == PIPE_POLYGON_MODE_LINE && + templ->fill_back == PIPE_POLYGON_MODE_LINE) { rast->unfilled_aa_line = AA_ALWAYS; } - else if (templ->fill_cw == PIPE_POLYGON_MODE_LINE || - templ->fill_ccw == PIPE_POLYGON_MODE_LINE) { + else if (templ->fill_front == PIPE_POLYGON_MODE_LINE || + templ->fill_back == PIPE_POLYGON_MODE_LINE) { rast->unfilled_aa_line = AA_SOMETIMES; } else { diff --git a/src/gallium/drivers/i965/brw_resource.c b/src/gallium/drivers/i965/brw_resource.c index 3b9854be588..1efdb1e0b4d 100644 --- a/src/gallium/drivers/i965/brw_resource.c +++ b/src/gallium/drivers/i965/brw_resource.c @@ -13,7 +13,7 @@ brw_resource_create(struct pipe_screen *screen, if (template->target == PIPE_BUFFER) return brw_buffer_create(screen, template); else - return brw_resource_create(screen, template); + return brw_texture_create(screen, template); } diff --git a/src/gallium/drivers/i965/brw_resource_texture.c b/src/gallium/drivers/i965/brw_resource_texture.c index 4fbb0c2484d..ffd0f38672c 100644 --- a/src/gallium/drivers/i965/brw_resource_texture.c +++ b/src/gallium/drivers/i965/brw_resource_texture.c @@ -210,7 +210,7 @@ brw_texture_get_handle(struct pipe_screen *screen, stride = tex->pitch * tex->cpp; - return bscreen->sws->bo_get_handle(tex->bo, whandle, stride); + return bscreen->sws->bo_get_handle(tex->bo, whandle, stride) == PIPE_OK; } diff --git a/src/gallium/drivers/i965/brw_screen.c b/src/gallium/drivers/i965/brw_screen.c index 172e222c057..7a7b9c1a5a9 100644 --- a/src/gallium/drivers/i965/brw_screen.c +++ b/src/gallium/drivers/i965/brw_screen.c @@ -149,7 +149,7 @@ brw_get_name(struct pipe_screen *screen) } static int -brw_get_param(struct pipe_screen *screen, int param) +brw_get_param(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: @@ -172,6 +172,8 @@ brw_get_param(struct pipe_screen *screen, int param) return 1; case PIPE_CAP_OCCLUSION_QUERY: return 0; + case PIPE_CAP_TIMER_QUERY: + return 0; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: @@ -192,7 +194,7 @@ brw_get_param(struct pipe_screen *screen, int param) } static float -brw_get_paramf(struct pipe_screen *screen, int param) +brw_get_paramf(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: diff --git a/src/gallium/drivers/i965/brw_sf.c b/src/gallium/drivers/i965/brw_sf.c index 9cceb4dbe52..5abf3848ab4 100644 --- a/src/gallium/drivers/i965/brw_sf.c +++ b/src/gallium/drivers/i965/brw_sf.c @@ -166,8 +166,8 @@ static enum pipe_error upload_sf_prog(struct brw_context *brw) case PIPE_PRIM_TRIANGLES: /* PIPE_NEW_RAST */ - if (rast->fill_cw != PIPE_POLYGON_MODE_FILL || - rast->fill_ccw != PIPE_POLYGON_MODE_FILL) + if (rast->fill_front != PIPE_POLYGON_MODE_FILL || + rast->fill_back != PIPE_POLYGON_MODE_FILL) key.primitive = SF_UNFILLED_TRIS; else key.primitive = SF_TRIANGLES; @@ -187,7 +187,7 @@ static enum pipe_error upload_sf_prog(struct brw_context *brw) key.do_twoside_color = rast->light_twoside; if (key.do_twoside_color) { - key.frontface_ccw = (rast->front_winding == PIPE_WINDING_CCW); + key.frontface_ccw = rast->front_ccw; } if (brw_search_cache(&brw->cache, BRW_SF_PROG, diff --git a/src/gallium/drivers/i965/brw_sf_state.c b/src/gallium/drivers/i965/brw_sf_state.c index 0ad91e03072..6c299a86b49 100644 --- a/src/gallium/drivers/i965/brw_sf_state.c +++ b/src/gallium/drivers/i965/brw_sf_state.c @@ -89,8 +89,8 @@ struct brw_sf_unit_key { unsigned line_smooth:1; unsigned point_sprite:1; unsigned point_attenuated:1; - unsigned front_face:2; - unsigned cull_mode:2; + unsigned front_ccw:1; + unsigned cull_face:2; unsigned flatshade_first:1; unsigned gl_rasterization_rules:1; unsigned line_last_pixel_enable:1; @@ -115,8 +115,8 @@ sf_unit_populate_key(struct brw_context *brw, struct brw_sf_unit_key *key) /* PIPE_NEW_RAST */ key->scissor = rast->scissor; - key->front_face = rast->front_winding; - key->cull_mode = rast->cull_mode; + key->front_ccw = rast->front_ccw; + key->cull_face = rast->cull_face; key->line_smooth = rast->line_smooth; key->line_width = rast->line_width; key->flatshade_first = rast->flatshade_first; @@ -183,22 +183,22 @@ sf_unit_create_from_key(struct brw_context *brw, if (key->scissor) sf.sf6.scissor = 1; - if (key->front_face == PIPE_WINDING_CCW) + if (key->front_ccw) sf.sf5.front_winding = BRW_FRONTWINDING_CCW; else sf.sf5.front_winding = BRW_FRONTWINDING_CW; - switch (key->cull_mode) { - case PIPE_WINDING_CCW: - case PIPE_WINDING_CW: - sf.sf6.cull_mode = (key->front_face == key->cull_mode ? - BRW_CULLMODE_FRONT : - BRW_CULLMODE_BACK); + switch (key->cull_face) { + case PIPE_FACE_FRONT: + sf.sf6.cull_mode = BRW_CULLMODE_FRONT; break; - case PIPE_WINDING_BOTH: + case PIPE_FACE_BACK: + sf.sf6.cull_mode = BRW_CULLMODE_BACK; + break; + case PIPE_FACE_FRONT_AND_BACK: sf.sf6.cull_mode = BRW_CULLMODE_BOTH; break; - case PIPE_WINDING_NONE: + case PIPE_FACE_NONE: sf.sf6.cull_mode = BRW_CULLMODE_NONE; break; default: @@ -284,7 +284,7 @@ static enum pipe_error upload_sf_unit( struct brw_context *brw ) */ total_grf = (align(key.total_grf, 16) / 16 - 1); viewport_transform = 1; - front_winding = (key.front_face == PIPE_WINDING_CCW ? + front_winding = (key.front_ccw ? BRW_FRONTWINDING_CCW : BRW_FRONTWINDING_CW); diff --git a/src/gallium/drivers/i965/brw_wm_state.c b/src/gallium/drivers/i965/brw_wm_state.c index ee970ac75bc..efc2d96be13 100644 --- a/src/gallium/drivers/i965/brw_wm_state.c +++ b/src/gallium/drivers/i965/brw_wm_state.c @@ -128,8 +128,9 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key) key->line_stipple = brw->curr.rast->templ.line_stipple_enable; - key->offset_enable = (brw->curr.rast->templ.offset_cw || - brw->curr.rast->templ.offset_ccw); + key->offset_enable = (brw->curr.rast->templ.offset_point || + brw->curr.rast->templ.offset_line || + brw->curr.rast->templ.offset_tri); key->offset_units = brw->curr.rast->templ.offset_units; key->offset_factor = brw->curr.rast->templ.offset_scale; diff --git a/src/gallium/drivers/identity/id_screen.c b/src/gallium/drivers/identity/id_screen.c index 7082d60d1c9..f71585e06f8 100644 --- a/src/gallium/drivers/identity/id_screen.c +++ b/src/gallium/drivers/identity/id_screen.c @@ -67,7 +67,7 @@ identity_screen_get_vendor(struct pipe_screen *_screen) static int identity_screen_get_param(struct pipe_screen *_screen, - int param) + enum pipe_cap param) { struct identity_screen *id_screen = identity_screen(_screen); struct pipe_screen *screen = id_screen->screen; @@ -78,7 +78,7 @@ identity_screen_get_param(struct pipe_screen *_screen, static float identity_screen_get_paramf(struct pipe_screen *_screen, - int param) + enum pipe_cap param) { struct identity_screen *id_screen = identity_screen(_screen); struct pipe_screen *screen = id_screen->screen; diff --git a/src/gallium/drivers/llvmpipe/Makefile b/src/gallium/drivers/llvmpipe/Makefile index 4ea367597e1..526e85c82e1 100644 --- a/src/gallium/drivers/llvmpipe/Makefile +++ b/src/gallium/drivers/llvmpipe/Makefile @@ -59,7 +59,7 @@ lp_tile_soa.c: lp_tile_soa.py ../../auxiliary/util/u_format_parse.py ../../auxil python lp_tile_soa.py ../../auxiliary/util/u_format.csv > $@ LDFLAGS += $(LLVM_LDFLAGS) -LIBS += $(GL_LIB_DEPS) -L../../auxiliary/ -lgallium libllvmpipe.a $(LLVM_LIBS) +LIBS += -L../../auxiliary/ -lgallium libllvmpipe.a $(LLVM_LIBS) $(GL_LIB_DEPS) LD=g++ $(PROGS): lp_test_main.o libllvmpipe.a diff --git a/src/gallium/drivers/llvmpipe/README b/src/gallium/drivers/llvmpipe/README index 3c3fd386b52..9c874acdedc 100644 --- a/src/gallium/drivers/llvmpipe/README +++ b/src/gallium/drivers/llvmpipe/README @@ -69,7 +69,15 @@ Requirements http://people.freedesktop.org/~jrfonseca/llvm/ and set the LLVM environment variable to the extracted path. - The version of LLVM from SVN ("2.7svn") from mid-March 2010 seems pretty + For MSVC there are two set of binaries: llvm-x.x-msvc32mt.7z and + llvm-x.x-msvc32mtd.7z . + + You have to set the LLVM=/path/to/llvm-x.x-msvc32mtd env var when passing + debug=yes to scons, and LLVM=/path/to/llvm-x.x-msvc32mt when building with + debug=no. This is necessary as LLVM builds as static library so the chosen + MS CRT must match. + + The version of LLVM from SVN ("2.7svn") from mid-March 2010 is pretty stable and has some features not in version 2.6. - scons (optional) diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript index 2911cf2179a..c155558aa54 100644 --- a/src/gallium/drivers/llvmpipe/SConscript +++ b/src/gallium/drivers/llvmpipe/SConscript @@ -85,4 +85,4 @@ if env['platform'] != 'embedded': ) env.InstallProgram(target) - Export('llvmpipe') +Export('llvmpipe') diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend.h b/src/gallium/drivers/llvmpipe/lp_bld_blend.h index ebbdb1a604c..5cecec3d7f9 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_blend.h @@ -29,17 +29,6 @@ #define LP_BLD_BLEND_H -/** - * @file - * LLVM IR building helpers interfaces. - * - * We use LLVM-C bindings for now. They are not documented, but follow the C++ - * interfaces very closely, and appear to be complete enough for code - * genration. See - * http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html - * for a standalone example. - */ - #include "gallivm/lp_bld.h" #include "pipe/p_format.h" @@ -75,6 +64,7 @@ LLVMValueRef lp_build_blend_aos(LLVMBuilderRef builder, const struct pipe_blend_state *blend, struct lp_type type, + unsigned rt, LLVMValueRef src, LLVMValueRef dst, LLVMValueRef const_, @@ -85,6 +75,7 @@ void lp_build_blend_soa(LLVMBuilderRef builder, const struct pipe_blend_state *blend, struct lp_type type, + unsigned rt, LLVMValueRef src[4], LLVMValueRef dst[4], LLVMValueRef const_[4], diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c index 3fa5e51cac5..70d08e71f6e 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c @@ -243,6 +243,9 @@ lp_build_blend_factor(struct lp_build_blend_aos_context *bld, } +/** + * Is (a OP b) == (b OP a)? + */ boolean lp_build_blend_func_commutative(unsigned func) { @@ -305,6 +308,7 @@ LLVMValueRef lp_build_blend_aos(LLVMBuilderRef builder, const struct pipe_blend_state *blend, struct lp_type type, + unsigned rt, LLVMValueRef src, LLVMValueRef dst, LLVMValueRef const_, @@ -314,11 +318,10 @@ lp_build_blend_aos(LLVMBuilderRef builder, LLVMValueRef src_term; LLVMValueRef dst_term; - /* FIXME */ - assert(blend->independent_blend_enable == 0); - assert(blend->rt[0].colormask == 0xf); + /* FIXME: color masking not implemented yet */ + assert(blend->rt[rt].colormask == 0xf); - if(!blend->rt[0].blend_enable) + if(!blend->rt[rt].blend_enable) return src; /* It makes no sense to blend unless values are normalized */ @@ -335,16 +338,16 @@ lp_build_blend_aos(LLVMBuilderRef builder, * combinations it is possible to reorder the operations and therefore saving * some instructions. */ - src_term = lp_build_blend_factor(&bld, src, blend->rt[0].rgb_src_factor, - blend->rt[0].alpha_src_factor, alpha_swizzle); - dst_term = lp_build_blend_factor(&bld, dst, blend->rt[0].rgb_dst_factor, - blend->rt[0].alpha_dst_factor, alpha_swizzle); + src_term = lp_build_blend_factor(&bld, src, blend->rt[rt].rgb_src_factor, + blend->rt[rt].alpha_src_factor, alpha_swizzle); + dst_term = lp_build_blend_factor(&bld, dst, blend->rt[rt].rgb_dst_factor, + blend->rt[rt].alpha_dst_factor, alpha_swizzle); lp_build_name(src_term, "src_term"); lp_build_name(dst_term, "dst_term"); - if(blend->rt[0].rgb_func == blend->rt[0].alpha_func) { - return lp_build_blend_func(&bld.base, blend->rt[0].rgb_func, src_term, dst_term); + if(blend->rt[rt].rgb_func == blend->rt[rt].alpha_func) { + return lp_build_blend_func(&bld.base, blend->rt[rt].rgb_func, src_term, dst_term); } else { /* Seperate RGB / A functions */ @@ -352,8 +355,8 @@ lp_build_blend_aos(LLVMBuilderRef builder, LLVMValueRef rgb; LLVMValueRef alpha; - rgb = lp_build_blend_func(&bld.base, blend->rt[0].rgb_func, src_term, dst_term); - alpha = lp_build_blend_func(&bld.base, blend->rt[0].alpha_func, src_term, dst_term); + rgb = lp_build_blend_func(&bld.base, blend->rt[rt].rgb_func, src_term, dst_term); + alpha = lp_build_blend_func(&bld.base, blend->rt[rt].alpha_func, src_term, dst_term); return lp_build_blend_swizzle(&bld, rgb, alpha, LP_BUILD_BLEND_SWIZZLE_RGBA, alpha_swizzle); } diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c index b7523eb9c13..b9c7a6ceed6 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c @@ -33,8 +33,8 @@ * Blending in SoA is much faster than AoS, especially when separate rgb/alpha * factors/functions are used, since no channel masking/shuffling is necessary * and we can achieve the full throughput of the SIMD operations. Furthermore - * the fragment shader output is also in SoA, so it fits nicely with the rest of - * the fragment pipeline. + * the fragment shader output is also in SoA, so it fits nicely with the rest + * of the fragment pipeline. * * The drawback is that to be displayed the color buffer needs to be in AoS * layout, so we need to tile/untile the color buffer before/after rendering. @@ -77,7 +77,7 @@ /** - * We may the same values several times, so we keep them here to avoid + * We may use the same values several times, so we keep them here to avoid * recomputing them. Also reusing the values allows us to do simplifications * that LLVM optimization passes wouldn't normally be able to do. */ @@ -98,16 +98,22 @@ struct lp_build_blend_soa_context /** * We store all factors in a table in order to eliminate redundant * multiplications later. + * Indexes are: factor[src,dst][color,term][r,g,b,a] */ LLVMValueRef factor[2][2][4]; /** * Table with all terms. + * Indexes are: term[src,dst][r,g,b,a] */ LLVMValueRef term[2][4]; }; +/** + * Build a single SOA blend factor for a color channel. + * \param i the color channel in [0,3] + */ static LLVMValueRef lp_build_blend_soa_factor(struct lp_build_blend_soa_context *bld, unsigned factor, unsigned i) @@ -191,6 +197,7 @@ lp_build_blend_soa_factor(struct lp_build_blend_soa_context *bld, /** * Generate blend code in SOA mode. + * \param rt render target index (to index the blend / colormask state) * \param src src/fragment color * \param dst dst/framebuffer color * \param con constant blend color @@ -200,6 +207,7 @@ void lp_build_blend_soa(LLVMBuilderRef builder, const struct pipe_blend_state *blend, struct lp_type type, + unsigned rt, LLVMValueRef src[4], LLVMValueRef dst[4], LLVMValueRef con[4], @@ -208,6 +216,8 @@ lp_build_blend_soa(LLVMBuilderRef builder, struct lp_build_blend_soa_context bld; unsigned i, j, k; + assert(rt < PIPE_MAX_COLOR_BUFS); + /* Setup build context */ memset(&bld, 0, sizeof bld); lp_build_context_init(&bld.base, builder, type); @@ -218,7 +228,8 @@ lp_build_blend_soa(LLVMBuilderRef builder, } for (i = 0; i < 4; ++i) { - if (blend->rt[0].colormask & (1 << i)) { + /* only compute blending for the color channels enabled for writing */ + if (blend->rt[rt].colormask & (1 << i)) { if (blend->logicop_enable) { if(!type.floating) { res[i] = lp_build_logicop(builder, blend->logicop_func, src[i], dst[i]); @@ -226,10 +237,10 @@ lp_build_blend_soa(LLVMBuilderRef builder, else res[i] = dst[i]; } - else if (blend->rt[0].blend_enable) { - unsigned src_factor = i < 3 ? blend->rt[0].rgb_src_factor : blend->rt[0].alpha_src_factor; - unsigned dst_factor = i < 3 ? blend->rt[0].rgb_dst_factor : blend->rt[0].alpha_dst_factor; - unsigned func = i < 3 ? blend->rt[0].rgb_func : blend->rt[0].alpha_func; + else if (blend->rt[rt].blend_enable) { + unsigned src_factor = i < 3 ? blend->rt[rt].rgb_src_factor : blend->rt[rt].alpha_src_factor; + unsigned dst_factor = i < 3 ? blend->rt[rt].rgb_dst_factor : blend->rt[rt].alpha_dst_factor; + unsigned func = i < 3 ? blend->rt[rt].rgb_func : blend->rt[rt].alpha_func; boolean func_commutative = lp_build_blend_func_commutative(func); /* It makes no sense to blend unless values are normalized */ @@ -269,9 +280,9 @@ lp_build_blend_soa(LLVMBuilderRef builder, /* XXX special case these combos to work around an apparent * bug in LLVM. * This hack disables the check for multiplication by zero - * in lp_bld_mul(). When we optimize away the multiplication, - * something goes wrong during code generation and we segfault - * at runtime. + * in lp_bld_mul(). When we optimize away the + * multiplication, something goes wrong during code + * generation and we segfault at runtime. */ LLVMValueRef zeroSave = bld.base.zero; bld.base.zero = NULL; @@ -287,7 +298,7 @@ lp_build_blend_soa(LLVMBuilderRef builder, /* See if this function has been previously applied */ for(j = 0; j < i; ++j) { - unsigned prev_func = j < 3 ? blend->rt[0].rgb_func : blend->rt[0].alpha_func; + unsigned prev_func = j < 3 ? blend->rt[rt].rgb_func : blend->rt[rt].alpha_func; unsigned func_reverse = lp_build_blend_func_reverse(func, prev_func); if((!func_reverse && diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c index 1b59a13c946..e05bbe5011a 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_depth.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.c @@ -72,6 +72,7 @@ #include "gallivm/lp_bld_const.h" #include "gallivm/lp_bld_logic.h" #include "gallivm/lp_bld_flow.h" +#include "gallivm/lp_bld_intr.h" #include "gallivm/lp_bld_debug.h" #include "gallivm/lp_bld_swizzle.h" @@ -445,6 +446,42 @@ get_s_shift_and_mask(const struct util_format_description *format_desc, } +/** + * Perform the occlusion test and increase the counter. + * Test the depth mask. Add the number of channel which has none zero mask + * into the occlusion counter. e.g. maskvalue is {-1, -1, -1, -1}. + * The counter will add 4. + * + * \param type holds element type of the mask vector. + * \param maskvalue is the depth test mask. + * \param counter is a pointer of the uint32 counter. + */ +static void +lp_build_occlusion_count(LLVMBuilderRef builder, + struct lp_type type, + LLVMValueRef maskvalue, + LLVMValueRef counter) +{ + LLVMValueRef countmask = lp_build_const_int_vec(type, 1); + LLVMValueRef countv = LLVMBuildAnd(builder, maskvalue, countmask, "countv"); + LLVMTypeRef i8v16 = LLVMVectorType(LLVMInt8Type(), 16); + LLVMValueRef counti = LLVMBuildBitCast(builder, countv, i8v16, "counti"); + LLVMValueRef maskarray[4] = { + LLVMConstInt(LLVMInt32Type(), 0, 0), + LLVMConstInt(LLVMInt32Type(), 4, 0), + LLVMConstInt(LLVMInt32Type(), 8, 0), + LLVMConstInt(LLVMInt32Type(), 12, 0), + }; + LLVMValueRef shufflemask = LLVMConstVector(maskarray, 4); + LLVMValueRef shufflev = LLVMBuildShuffleVector(builder, counti, LLVMGetUndef(i8v16), shufflemask, "shufflev"); + LLVMValueRef shuffle = LLVMBuildBitCast(builder, shufflev, LLVMInt32Type(), "shuffle"); + LLVMValueRef count = lp_build_intrinsic_unary(builder, "llvm.ctpop.i32", LLVMInt32Type(), shuffle); + LLVMValueRef orig = LLVMBuildLoad(builder, counter, "orig"); + LLVMValueRef incr = LLVMBuildAdd(builder, orig, count, "incr"); + LLVMBuildStore(builder, incr, counter); +} + + /** * Generate code for performing depth and/or stencil tests. @@ -470,7 +507,8 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, LLVMValueRef stencil_refs[2], LLVMValueRef z_src, LLVMValueRef zs_dst_ptr, - LLVMValueRef face) + LLVMValueRef face, + LLVMValueRef counter) { struct lp_build_context bld; struct lp_build_context sbld; @@ -682,4 +720,7 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, if (depth->enabled && stencil[0].enabled) lp_build_mask_update(mask, z_pass); + + if (counter) + lp_build_occlusion_count(builder, type, mask->value, counter); } diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.h b/src/gallium/drivers/llvmpipe/lp_bld_depth.h index 27dd46b625d..e257a5bd7d0 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_depth.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.h @@ -60,7 +60,8 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, LLVMValueRef stencil_refs[2], LLVMValueRef zs_src, LLVMValueRef zs_dst_ptr, - LLVMValueRef facing); + LLVMValueRef facing, + LLVMValueRef counter); #endif /* !LP_BLD_DEPTH_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index 4e597b24796..de7fe7a1796 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -82,11 +82,7 @@ struct llvmpipe_context { unsigned dirty; /**< Mask of LP_NEW_x flags */ - /* Counter for occlusion queries. Note this supports overlapping - * queries. - */ - uint64_t occlusion_count; - unsigned active_query_count; + int active_query_count; /** Mapped vertex buffers */ ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS]; diff --git a/src/gallium/drivers/llvmpipe/lp_debug.h b/src/gallium/drivers/llvmpipe/lp_debug.h index ee818143610..92fb2b3ee5b 100644 --- a/src/gallium/drivers/llvmpipe/lp_debug.h +++ b/src/gallium/drivers/llvmpipe/lp_debug.h @@ -39,16 +39,13 @@ st_print_current(void); #define DEBUG_PIPE 0x1 #define DEBUG_TGSI 0x2 #define DEBUG_TEX 0x4 -#define DEBUG_ASM 0x8 #define DEBUG_SETUP 0x10 #define DEBUG_RAST 0x20 #define DEBUG_QUERY 0x40 #define DEBUG_SCREEN 0x80 -#define DEBUG_JIT 0x100 #define DEBUG_SHOW_TILES 0x200 #define DEBUG_SHOW_SUBTILES 0x400 #define DEBUG_COUNTERS 0x800 -#define DEBUG_NO_LLVM_OPT 0x1000 #ifdef DEBUG diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c index 644b821957a..e1425435e19 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.c +++ b/src/gallium/drivers/llvmpipe/lp_flush.c @@ -31,6 +31,7 @@ #include "pipe/p_defines.h" +#include "util/u_string.h" #include "draw/draw_context.h" #include "lp_flush.h" #include "lp_context.h" @@ -71,25 +72,25 @@ llvmpipe_flush( struct pipe_context *pipe, } /* Enable to dump BMPs of the color/depth buffers each frame */ -#if 0 - if (flags & PIPE_FLUSH_FRAME) { - static unsigned frame_no = 1; - char filename[256]; - unsigned i; - - for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) { - util_snprintf(filename, sizeof(filename), "cbuf%u_%u", i, frame_no); - debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.cbufs[0]); - } + if (0) { + if (flags & PIPE_FLUSH_FRAME) { + static unsigned frame_no = 1; + char filename[256]; + unsigned i; + + for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) { + util_snprintf(filename, sizeof(filename), "cbuf%u_%u", i, frame_no); + debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.cbufs[0]); + } - if (0) { - util_snprintf(filename, sizeof(filename), "zsbuf_%u", frame_no); - debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.zsbuf); - } + if (0) { + util_snprintf(filename, sizeof(filename), "zsbuf_%u", frame_no); + debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.zsbuf); + } - ++frame_no; + ++frame_no; + } } -#endif } diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index 30e206a2b42..23aa34ddec1 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -38,7 +38,7 @@ #include "util/u_memory.h" #include "util/u_cpu_detect.h" #include "gallivm/lp_bld_init.h" -#include "lp_debug.h" +#include "gallivm/lp_bld_debug.h" #include "lp_screen.h" #include "gallivm/lp_bld_intr.h" #include "lp_jit.h" @@ -151,9 +151,9 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) screen->context_ptr_type = LLVMPointerType(context_type, 0); } -#ifdef DEBUG - LLVMDumpModule(screen->module); -#endif + if (gallivm_debug & GALLIVM_DEBUG_IR) { + LLVMDumpModule(screen->module); + } } @@ -181,7 +181,7 @@ lp_jit_screen_init(struct llvmpipe_screen *screen) screen->pass = LLVMCreateFunctionPassManager(screen->provider); LLVMAddTargetData(screen->target, screen->pass); - if ((LP_DEBUG & DEBUG_NO_LLVM_OPT) == 0) { + if ((gallivm_debug & GALLIVM_DEBUG_NO_OPT) == 0) { /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, * but there are more on SVN. */ /* TODO: Add more passes */ @@ -196,6 +196,11 @@ lp_jit_screen_init(struct llvmpipe_screen *screen) LLVMAddInstructionCombiningPass(screen->pass); } LLVMAddGVNPass(screen->pass); + } else { + /* We need at least this pass to prevent the backends to fail in + * unexpected ways. + */ + LLVMAddPromoteMemoryToRegisterPass(screen->pass); } lp_jit_init_globals(screen); diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index 5d0268c68c4..8dee0413019 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -146,13 +146,9 @@ enum { lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_BLEND_COLOR, "blend_color") #define lp_jit_context_textures(_builder, _ptr) \ - lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES, "textures") + lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CTX_TEXTURES, "textures") -/** Indexes into jit_function[] array */ -#define RAST_WHOLE 0 -#define RAST_EDGE_TEST 1 - typedef void (*lp_jit_frag_func)(const struct lp_jit_context *context, @@ -169,7 +165,38 @@ typedef void const int32_t c3, const int32_t *step1, const int32_t *step2, - const int32_t *step3); + const int32_t *step3, + uint32_t *counter); + + +/** cast wrapper to avoid compiler warnings */ +static INLINE lp_jit_frag_func +cast_voidptr_to_lp_jit_frag_func(void *v) +{ + union { + void *v; + lp_jit_frag_func f; + } u; + assert(sizeof(u.v) == sizeof(u.f)); + u.v = v; + return u.f; +} + + +/** cast wrapper */ +static INLINE void * +cast_lp_jit_frag_func_to_voidptr(lp_jit_frag_func f) +{ + union { + void *v; + lp_jit_frag_func f; + } u; + assert(sizeof(u.v) == sizeof(u.f)); + u.f = f; + return u.v; +} + + void diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c index 5554285425d..c23e9839063 100644 --- a/src/gallium/drivers/llvmpipe/lp_query.c +++ b/src/gallium/drivers/llvmpipe/lp_query.c @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2010 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,15 +19,15 @@ * 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS 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. * **************************************************************************/ -/* Author: - * Keith Whitwell <[email protected]> +/* Authors: + * Keith Whitwell, Qicheng Christopher Li, Brian Paul */ #include "draw/draw_context.h" @@ -34,12 +35,10 @@ #include "util/u_memory.h" #include "lp_context.h" #include "lp_query.h" +#include "lp_rast.h" +#include "lp_rast_priv.h" #include "lp_state.h" - -struct llvmpipe_query { - uint64_t start; - uint64_t end; -}; +#include "lp_setup_context.h" static struct llvmpipe_query *llvmpipe_query( struct pipe_query *p ) @@ -51,15 +50,46 @@ static struct pipe_query * llvmpipe_create_query(struct pipe_context *pipe, unsigned type) { + struct llvmpipe_query *pq; + assert(type == PIPE_QUERY_OCCLUSION_COUNTER); - return (struct pipe_query *)CALLOC_STRUCT( llvmpipe_query ); + + pq = CALLOC_STRUCT( llvmpipe_query ); + if (pq) { + pipe_mutex_init(pq->mutex); + } + + return (struct pipe_query *) pq; } static void llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q) { - FREE(q); + struct llvmpipe_query *pq = llvmpipe_query(q); + pipe_mutex_destroy(pq->mutex); + FREE(pq); +} + + +static boolean +llvmpipe_get_query_result(struct pipe_context *pipe, + struct pipe_query *q, + boolean wait, + uint64_t *result ) +{ + struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); + struct llvmpipe_query *pq = llvmpipe_query(q); + + if (!pq->done) { + lp_setup_flush(llvmpipe->setup, TRUE); + } + + if (pq->done) { + *result = pq->result; + } + + return pq->done; } @@ -67,9 +97,23 @@ static void llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); - struct llvmpipe_query *sq = llvmpipe_query(q); - - sq->start = llvmpipe->occlusion_count; + struct llvmpipe_query *pq = llvmpipe_query(q); + + /* Check if the query is already in the scene. If so, we need to + * flush the scene now. Real apps shouldn't re-use a query in a + * frame of rendering. + */ + if (pq->binned) { + struct pipe_fence_handle *fence; + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &fence); + if (fence) { + pipe->screen->fence_finish(pipe->screen, fence, 0); + pipe->screen->fence_reference(pipe->screen, &fence, NULL); + } + } + + lp_setup_begin_query(llvmpipe->setup, pq); + llvmpipe->active_query_count++; llvmpipe->dirty |= LP_NEW_QUERY; } @@ -79,26 +123,16 @@ static void llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); - struct llvmpipe_query *sq = llvmpipe_query(q); + struct llvmpipe_query *pq = llvmpipe_query(q); + lp_setup_end_query(llvmpipe->setup, pq); + + assert(llvmpipe->active_query_count); llvmpipe->active_query_count--; - sq->end = llvmpipe->occlusion_count; llvmpipe->dirty |= LP_NEW_QUERY; } -static boolean -llvmpipe_get_query_result(struct pipe_context *pipe, - struct pipe_query *q, - boolean wait, - uint64_t *result ) -{ - struct llvmpipe_query *sq = llvmpipe_query(q); - *result = sq->end - sq->start; - return TRUE; -} - - void llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe ) { llvmpipe->pipe.create_query = llvmpipe_create_query; diff --git a/src/gallium/drivers/llvmpipe/lp_query.h b/src/gallium/drivers/llvmpipe/lp_query.h index fa9fcd87139..721c41cb5c9 100644 --- a/src/gallium/drivers/llvmpipe/lp_query.h +++ b/src/gallium/drivers/llvmpipe/lp_query.h @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2010 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -25,14 +26,33 @@ * **************************************************************************/ -/* Author: - * Keith Whitwell +/* Authors: + * Keith Whitwell, Qicheng Christopher Li, Brian Paul */ #ifndef LP_QUERY_H #define LP_QUERY_H +#include <limits.h> +#include "os/os_thread.h" +#include "lp_limits.h" + + struct llvmpipe_context; + + +struct llvmpipe_query { + uint64_t count[LP_MAX_THREADS]; /**< a counter for each thread */ + uint64_t result; /**< total of all counters */ + + pipe_mutex mutex; + unsigned num_tiles, tile_count; + + boolean done; + boolean binned; /**< has this query been binned in the scene? */ +}; + + extern void llvmpipe_init_query_funcs(struct llvmpipe_context * ); diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index a00a592f2fe..6bb868bf1a9 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -34,6 +34,7 @@ #include "lp_debug.h" #include "lp_fence.h" #include "lp_perf.h" +#include "lp_query.h" #include "lp_rast.h" #include "lp_rast_priv.h" #include "lp_tile_soa.h" @@ -442,7 +443,7 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task, color, depth, INT_MIN, INT_MIN, INT_MIN, - NULL, NULL, NULL ); + NULL, NULL, NULL, &task->vis_counter); } } } @@ -502,7 +503,8 @@ void lp_rast_shade_quads( struct lp_rasterizer_task *task, c1, c2, c3, inputs->step[0], inputs->step[1], - inputs->step[2]); + inputs->step[2], + &task->vis_counter); } @@ -602,6 +604,60 @@ lp_rast_fence(struct lp_rasterizer_task *task, } +/** + * Begin a new occlusion query. + * This is a bin command put in all bins. + * Called per thread. + */ +void +lp_rast_begin_query(struct lp_rasterizer_task *task, + const union lp_rast_cmd_arg arg) +{ + /* Reset the the per-task counter */ + task->vis_counter = 0; +} + + +/** + * End the current occlusion query. + * This is a bin command put in all bins. + * Called per thread. + */ +void +lp_rast_end_query(struct lp_rasterizer_task *task, + const union lp_rast_cmd_arg arg) +{ + struct llvmpipe_query *pq = arg.query_obj; + + pipe_mutex_lock(pq->mutex); + { + /* Accumulate the visible fragment counter from this tile in + * the query object. + */ + pq->count[task->thread_index] += task->vis_counter; + + /* check if this is the last tile in the scene */ + pq->tile_count++; + if (pq->tile_count == pq->num_tiles) { + uint i; + + /* sum the per-thread counters for the query */ + pq->result = 0; + for (i = 0; i < LP_MAX_THREADS; i++) { + pq->result += pq->count[i]; + } + + /* reset counters (in case this query is re-used in the scene) */ + memset(pq->count, 0, sizeof(pq->count)); + + pq->tile_count = 0; + pq->binned = FALSE; + pq->done = TRUE; + } + } + pipe_mutex_unlock(pq->mutex); +} + /** @@ -650,6 +706,8 @@ static struct { RAST(set_state), RAST(store_color), RAST(fence), + RAST(begin_query), + RAST(end_query), }; static void @@ -956,3 +1014,5 @@ lp_rast_get_num_threads( struct lp_rasterizer *rast ) { return rast->num_threads; } + + diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index e2f6f926779..881f475189e 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -157,6 +157,7 @@ union lp_rast_cmd_arg { uint8_t clear_color[4]; unsigned clear_zstencil; struct lp_fence *fence; + struct llvmpipe_query *query_obj; }; @@ -233,4 +234,11 @@ void lp_rast_store_color( struct lp_rasterizer_task *, const union lp_rast_cmd_arg ); +void lp_rast_begin_query(struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); + +void lp_rast_end_query(struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); + + #endif diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h index 5884d12721e..efc013ff3f0 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h @@ -33,6 +33,7 @@ #include "gallivm/lp_bld_debug.h" #include "lp_rast.h" #include "lp_scene.h" +#include "lp_state.h" #include "lp_texture.h" #include "lp_tile_soa.h" #include "lp_limits.h" @@ -59,6 +60,9 @@ struct lp_rasterizer_task /** "my" index */ unsigned thread_index; + /* occlude counter for visiable pixels */ + uint32_t vis_counter; + pipe_semaphore work_ready; pipe_semaphore work_done; }; @@ -221,7 +225,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task, color, depth, INT_MIN, INT_MIN, INT_MIN, - NULL, NULL, NULL ); + NULL, NULL, NULL, &task->vis_counter ); } diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index 887f2dbad91..59e4c18ad05 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -30,7 +30,6 @@ #include "util/u_memory.h" #include "util/u_inlines.h" #include "util/u_simple_list.h" -#include "util/u_surface.h" #include "lp_scene.h" #include "lp_scene_queue.h" @@ -210,25 +209,31 @@ lp_scene_reset(struct lp_scene *scene ) -void +struct cmd_block * lp_bin_new_cmd_block( struct cmd_block_list *list ) { struct cmd_block *block = MALLOC_STRUCT(cmd_block); - list->tail->next = block; - list->tail = block; - block->next = NULL; - block->count = 0; + if (block) { + list->tail->next = block; + list->tail = block; + block->next = NULL; + block->count = 0; + } + return block; } -void +struct data_block * lp_bin_new_data_block( struct data_block_list *list ) { struct data_block *block = MALLOC_STRUCT(data_block); - list->tail->next = block; - list->tail = block; - block->next = NULL; - block->used = 0; + if (block) { + list->tail->next = block; + list->tail = block; + block->next = NULL; + block->used = 0; + } + return block; } diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h index 9467cd6f16d..22d619fdbc3 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.h +++ b/src/gallium/drivers/llvmpipe/lp_scene.h @@ -158,9 +158,9 @@ boolean lp_scene_is_empty(struct lp_scene *scene ); void lp_scene_reset(struct lp_scene *scene ); -void lp_bin_new_data_block( struct data_block_list *list ); +struct data_block *lp_bin_new_data_block( struct data_block_list *list ); -void lp_bin_new_cmd_block( struct cmd_block_list *list ); +struct cmd_block *lp_bin_new_cmd_block( struct cmd_block_list *list ); unsigned lp_scene_data_size( const struct lp_scene *scene ); @@ -181,15 +181,19 @@ static INLINE void * lp_scene_alloc( struct lp_scene *scene, unsigned size) { struct data_block_list *list = &scene->data; - - if (list->tail->used + size > DATA_BLOCK_SIZE) { - lp_bin_new_data_block( list ); + struct data_block *tail = list->tail; + + if (tail->used + size > DATA_BLOCK_SIZE) { + tail = lp_bin_new_data_block( list ); + if (!tail) { + /* out of memory */ + return NULL; + } } scene->scene_size += size; { - struct data_block *tail = list->tail; ubyte *data = tail->data + tail->used; tail->used += size; return data; @@ -205,15 +209,17 @@ lp_scene_alloc_aligned( struct lp_scene *scene, unsigned size, unsigned alignment ) { struct data_block_list *list = &scene->data; + struct data_block *tail = list->tail; - if (list->tail->used + size + alignment - 1 > DATA_BLOCK_SIZE) { - lp_bin_new_data_block( list ); + if (tail->used + size + alignment - 1 > DATA_BLOCK_SIZE) { + tail = lp_bin_new_data_block( list ); + if (!tail) + return NULL; } scene->scene_size += size; { - struct data_block *tail = list->tail; ubyte *data = tail->data + tail->used; unsigned offset = (((uintptr_t)data + alignment - 1) & ~(alignment - 1)) - (uintptr_t)data; tail->used += offset + size; @@ -257,16 +263,21 @@ lp_scene_bin_command( struct lp_scene *scene, { struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); struct cmd_block_list *list = &bin->commands; + struct cmd_block *tail = list->tail; assert(x < scene->tiles_x); assert(y < scene->tiles_y); - if (list->tail->count == CMD_BLOCK_MAX) { - lp_bin_new_cmd_block( list ); + if (tail->count == CMD_BLOCK_MAX) { + tail = lp_bin_new_cmd_block( list ); + if (!tail) { + /* out of memory - simply ignore this command (for now) */ + return; + } + assert(tail->count == 0); } { - struct cmd_block *tail = list->tail; unsigned i = tail->count; tail->cmd[i] = cmd; tail->arg[i] = arg; diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 5f50446f846..cedc08e9292 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -34,6 +34,7 @@ #include "pipe/p_defines.h" #include "pipe/p_screen.h" +#include "gallivm/lp_bld_limits.h" #include "lp_texture.h" #include "lp_fence.h" #include "lp_jit.h" @@ -52,16 +53,13 @@ static const struct debug_named_value lp_debug_flags[] = { { "pipe", DEBUG_PIPE }, { "tgsi", DEBUG_TGSI }, { "tex", DEBUG_TEX }, - { "asm", DEBUG_ASM }, { "setup", DEBUG_SETUP }, { "rast", DEBUG_RAST }, { "query", DEBUG_QUERY }, { "screen", DEBUG_SCREEN }, - { "jit", DEBUG_JIT }, { "show_tiles", DEBUG_SHOW_TILES }, { "show_subtiles", DEBUG_SHOW_SUBTILES }, { "counters", DEBUG_COUNTERS }, - { "nopt", DEBUG_NO_LLVM_OPT }, {NULL, 0} }; #endif @@ -82,7 +80,7 @@ llvmpipe_get_name(struct pipe_screen *screen) static int -llvmpipe_get_param(struct pipe_screen *screen, int param) +llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: @@ -107,6 +105,8 @@ llvmpipe_get_param(struct pipe_screen *screen, int param) return PIPE_MAX_COLOR_BUFS; case PIPE_CAP_OCCLUSION_QUERY: return 1; + case PIPE_CAP_TIMER_QUERY: + return 0; case PIPE_CAP_TEXTURE_MIRROR_CLAMP: return 1; case PIPE_CAP_TEXTURE_MIRROR_REPEAT: @@ -124,7 +124,7 @@ llvmpipe_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; case PIPE_CAP_INDEP_BLEND_ENABLE: - return 0; + return 1; case PIPE_CAP_INDEP_BLEND_FUNC: return 0; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: @@ -133,14 +133,44 @@ llvmpipe_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return 0; + case PIPE_CAP_MAX_VS_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_ALU_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_ALU_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_TEX_INDIRECTIONS: + case PIPE_CAP_MAX_FS_TEX_INDIRECTIONS: + /* There is no limit in number of instructions beyond available memory */ + return 32768; + case PIPE_CAP_MAX_VS_CONTROL_FLOW_DEPTH: + case PIPE_CAP_MAX_FS_CONTROL_FLOW_DEPTH: + return LP_MAX_TGSI_NESTING; + case PIPE_CAP_MAX_VS_INPUTS: + case PIPE_CAP_MAX_FS_INPUTS: + return PIPE_MAX_ATTRIBS; + case PIPE_CAP_MAX_FS_CONSTS: + case PIPE_CAP_MAX_VS_CONSTS: + /* There is no limit in number of constants beyond available memory */ + return 32768; + case PIPE_CAP_MAX_VS_TEMPS: + case PIPE_CAP_MAX_FS_TEMPS: + return LP_MAX_TGSI_TEMPS; + case PIPE_CAP_MAX_VS_ADDRS: + case PIPE_CAP_MAX_FS_ADDRS: + return LP_MAX_TGSI_ADDRS; + case PIPE_CAP_MAX_VS_PREDS: + case PIPE_CAP_MAX_FS_PREDS: + return LP_MAX_TGSI_PREDS; default: + assert(0); return 0; } } static float -llvmpipe_get_paramf(struct pipe_screen *screen, int param) +llvmpipe_get_paramf(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: @@ -155,7 +185,13 @@ llvmpipe_get_paramf(struct pipe_screen *screen, int param) return 16.0; /* not actually signficant at this time */ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: return 16.0; /* arbitrary */ + case PIPE_CAP_GUARD_BAND_LEFT: + case PIPE_CAP_GUARD_BAND_TOP: + case PIPE_CAP_GUARD_BAND_RIGHT: + case PIPE_CAP_GUARD_BAND_BOTTOM: + return 0.0; default: + assert(0); return 0; } } @@ -270,7 +306,16 @@ llvmpipe_destroy_screen( struct pipe_screen *_screen ) struct pipe_screen * llvmpipe_create_screen(struct sw_winsys *winsys) { - struct llvmpipe_screen *screen = CALLOC_STRUCT(llvmpipe_screen); + struct llvmpipe_screen *screen; + +#ifdef PIPE_ARCH_X86 + /* require SSE2 due to LLVM PR6960. */ + util_cpu_detect(); + if (!util_cpu_caps.has_sse2) + return NULL; +#endif + + screen = CALLOC_STRUCT(llvmpipe_screen); #ifdef DEBUG LP_DEBUG = debug_get_flags_option("LP_DEBUG", lp_debug_flags, 0 ); diff --git a/src/gallium/drivers/llvmpipe/lp_screen.h b/src/gallium/drivers/llvmpipe/lp_screen.h index 4f394326103..eb40f6823f5 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.h +++ b/src/gallium/drivers/llvmpipe/lp_screen.h @@ -60,10 +60,9 @@ struct llvmpipe_screen unsigned num_threads; - /* Increments whenever textures are modified. Contexts can track - * this. + /* Increments whenever textures are modified. Contexts can track this. */ - unsigned timestamp; + unsigned timestamp; }; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 1a2cd55b164..656e6cc38a6 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -32,18 +32,20 @@ * lp_setup_flush(). */ +#include <limits.h> + #include "pipe/p_defines.h" #include "util/u_framebuffer.h" #include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_pack_color.h" -#include "util/u_surface.h" #include "lp_context.h" #include "lp_scene.h" #include "lp_scene_queue.h" #include "lp_texture.h" #include "lp_debug.h" #include "lp_fence.h" +#include "lp_query.h" #include "lp_rast.h" #include "lp_setup_context.h" #include "lp_screen.h" @@ -418,7 +420,8 @@ lp_setup_set_fs_functions( struct lp_setup_context *setup, lp_jit_frag_func jit_function1, boolean opaque ) { - LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) jit_function0); + LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, + cast_lp_jit_frag_func_to_voidptr(jit_function0)); /* FIXME: reference count */ setup->fs.current.jit_function[0] = jit_function0; @@ -644,16 +647,19 @@ lp_setup_update_state( struct lp_setup_context *setup ) stored = lp_scene_alloc_aligned(scene, 4 * 16, 16); - /* smear each blend color component across 16 ubyte elements */ - for (i = 0; i < 4; ++i) { - uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); - for (j = 0; j < 16; ++j) - stored[i*16 + j] = c; - } + if (stored) { + /* smear each blend color component across 16 ubyte elements */ + for (i = 0; i < 4; ++i) { + uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); + for (j = 0; j < 16; ++j) + stored[i*16 + j] = c; + } - setup->blend_color.stored = stored; + setup->blend_color.stored = stored; + + setup->fs.current.jit_context.blend_color = setup->blend_color.stored; + } - setup->fs.current.jit_context.blend_color = setup->blend_color.stored; setup->dirty |= LP_SETUP_NEW_FS; } @@ -662,17 +668,19 @@ lp_setup_update_state( struct lp_setup_context *setup ) stored = lp_scene_alloc_aligned(scene, 4 * sizeof(int32_t), 16); - stored[0] = (float) setup->scissor.current.minx; - stored[1] = (float) setup->scissor.current.miny; - stored[2] = (float) setup->scissor.current.maxx; - stored[3] = (float) setup->scissor.current.maxy; + if (stored) { + stored[0] = (float) setup->scissor.current.minx; + stored[1] = (float) setup->scissor.current.miny; + stored[2] = (float) setup->scissor.current.maxx; + stored[3] = (float) setup->scissor.current.maxy; - setup->scissor.stored = stored; + setup->scissor.stored = stored; - setup->fs.current.jit_context.scissor_xmin = stored[0]; - setup->fs.current.jit_context.scissor_ymin = stored[1]; - setup->fs.current.jit_context.scissor_xmax = stored[2]; - setup->fs.current.jit_context.scissor_ymax = stored[3]; + setup->fs.current.jit_context.scissor_xmin = stored[0]; + setup->fs.current.jit_context.scissor_ymin = stored[1]; + setup->fs.current.jit_context.scissor_xmax = stored[2]; + setup->fs.current.jit_context.scissor_ymax = stored[3]; + } setup->dirty |= LP_SETUP_NEW_FS; } @@ -852,3 +860,40 @@ fail: return NULL; } + +/** + * Put a BeginQuery command into all bins. + */ +void +lp_setup_begin_query(struct lp_setup_context *setup, + struct llvmpipe_query *pq) +{ + struct lp_scene * scene = lp_setup_get_current_scene(setup); + union lp_rast_cmd_arg cmd_arg; + + /* init the query to its beginning state */ + pq->done = FALSE; + pq->tile_count = 0; + pq->num_tiles = scene->tiles_x * scene->tiles_y; + assert(pq->num_tiles > 0); + + memset(pq->count, 0, sizeof(pq->count)); /* reset all counters */ + + cmd_arg.query_obj = pq; + lp_scene_bin_everywhere(scene, lp_rast_begin_query, cmd_arg); + pq->binned = TRUE; +} + + +/** + * Put an EndQuery command into all bins. + */ +void +lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) +{ + struct lp_scene * scene = lp_setup_get_current_scene(setup); + union lp_rast_cmd_arg cmd_arg; + + cmd_arg.query_obj = pq; + lp_scene_bin_everywhere(scene, lp_rast_end_query, cmd_arg); +} diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index e10d37d8d04..10db03b9c69 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -53,12 +53,15 @@ struct lp_shader_input { }; struct pipe_resource; +struct pipe_query; struct pipe_surface; struct pipe_blend_color; struct pipe_screen; struct pipe_framebuffer_state; struct lp_fragment_shader; struct lp_jit_context; +struct llvmpipe_query; + struct lp_setup_context * lp_setup_create( struct pipe_context *pipe, @@ -140,5 +143,12 @@ void lp_setup_set_vertex_info( struct lp_setup_context *setup, struct vertex_info *info ); +void +lp_setup_begin_query(struct lp_setup_context *setup, + struct llvmpipe_query *pq); + +void +lp_setup_end_query(struct lp_setup_context *setup, + struct llvmpipe_query *pq); #endif diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index f8a58165733..306cb6e27d2 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -205,8 +205,14 @@ static void setup_tri_coefficients( struct lp_setup_context *setup, switch (setup->fs.input[slot].interp) { case LP_INTERP_CONSTANT: - for (i = 0; i < NUM_CHANNELS; i++) - constant_coef(setup, tri, slot+1, v3[vert_attr][i], i); + if (setup->flatshade_first) { + for (i = 0; i < NUM_CHANNELS; i++) + constant_coef(setup, tri, slot+1, v1[vert_attr][i], i); + } + else { + for (i = 0; i < NUM_CHANNELS; i++) + constant_coef(setup, tri, slot+1, v3[vert_attr][i], i); + } break; case LP_INTERP_LINEAR: @@ -665,14 +671,14 @@ void lp_setup_choose_triangle( struct lp_setup_context *setup ) { switch (setup->cullmode) { - case PIPE_WINDING_NONE: + case PIPE_FACE_NONE: setup->triangle = triangle_both; break; - case PIPE_WINDING_CCW: - setup->triangle = triangle_cw; + case PIPE_FACE_BACK: + setup->triangle = setup->ccw_is_frontface ? triangle_ccw : triangle_cw; break; - case PIPE_WINDING_CW: - setup->triangle = triangle_ccw; + case PIPE_FACE_FRONT: + setup->triangle = setup->ccw_is_frontface ? triangle_cw : triangle_ccw; break; default: setup->triangle = triangle_nop; diff --git a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c index 5d3122e8ba2..f6a424f25a8 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c @@ -131,11 +131,12 @@ static INLINE const_float4_ptr get_vert( const void *vertex_buffer, * draw elements / indexed primitives */ static void -lp_setup_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) +lp_setup_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr) { struct lp_setup_context *setup = lp_setup_context(vbr); const unsigned stride = setup->vertex_info->size * sizeof(float); const void *vertex_buffer = setup->vertex_buffer; + const boolean flatshade_first = setup->flatshade_first; unsigned i; lp_setup_update_state(setup); @@ -178,35 +179,28 @@ lp_setup_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_TRIANGLES: - if (setup->flatshade_first) { - for (i = 2; i < nr; i += 3) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-2], stride) ); - } - } - else { - for (i = 2; i < nr; i += 3) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - } + for (i = 2; i < nr; i += 3) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); } break; case PIPE_PRIM_TRIANGLE_STRIP: - if (setup->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i += 1) { + /* emit first triangle vertex as first triangle vertex */ setup->triangle( setup, + get_vert(vertex_buffer, indices[i-2], stride), get_vert(vertex_buffer, indices[i+(i&1)-1], stride), - get_vert(vertex_buffer, indices[i-(i&1)], stride), - get_vert(vertex_buffer, indices[i-2], stride) ); + get_vert(vertex_buffer, indices[i-(i&1)], stride) ); + } } else { for (i = 2; i < nr; i += 1) { + /* emit last triangle vertex as last triangle vertex */ setup->triangle( setup, get_vert(vertex_buffer, indices[i+(i&1)-2], stride), get_vert(vertex_buffer, indices[i-(i&1)-1], stride), @@ -216,16 +210,18 @@ lp_setup_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_TRIANGLE_FAN: - if (setup->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i += 1) { + /* emit first non-spoke vertex as first vertex */ setup->triangle( setup, + get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[0], stride), - get_vert(vertex_buffer, indices[i-1], stride) ); + get_vert(vertex_buffer, indices[0], stride) ); } } else { for (i = 2; i < nr; i += 1) { + /* emit last non-spoke vertex as last vertex */ setup->triangle( setup, get_vert(vertex_buffer, indices[0], stride), get_vert(vertex_buffer, indices[i-1], stride), @@ -235,43 +231,88 @@ lp_setup_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_QUADS: - for (i = 3; i < nr; i += 4) { - setup->triangle( setup, + /* GL quads don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride) ); + + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, get_vert(vertex_buffer, indices[i-3], stride), get_vert(vertex_buffer, indices[i-2], stride), get_vert(vertex_buffer, indices[i-0], stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_QUAD_STRIP: - for (i = 3; i < nr; i += 2) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); + /* GL quad strips don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_POLYGON: /* Almost same as tri fan but the _first_ vertex specifies the flat - * shading color. Note that the first polygon vertex is passed as - * the last triangle vertex here. - * flatshade_first state makes no difference. + * shading color. */ - for (i = 2; i < nr; i += 1) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[0], stride) ); + if (flatshade_first) { + /* emit first polygon vertex as first triangle vertex */ + for (i = 2; i < nr; i += 1) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[0], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } + } + else { + /* emit first polygon vertex as last triangle vertex */ + for (i = 2; i < nr; i += 1) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[0], stride) ); + } } break; @@ -292,6 +333,7 @@ lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) const unsigned stride = setup->vertex_info->size * sizeof(float); const void *vertex_buffer = (void *) get_vert(setup->vertex_buffer, start, stride); + const boolean flatshade_first = setup->flatshade_first; unsigned i; lp_setup_update_state(setup); @@ -334,35 +376,27 @@ lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_TRIANGLES: - if (setup->flatshade_first) { - for (i = 2; i < nr; i += 3) { - setup->triangle( setup, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-2, stride) ); - } - } - else { - for (i = 2; i < nr; i += 3) { - setup->triangle( setup, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); - } + for (i = 2; i < nr; i += 3) { + setup->triangle( setup, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); } break; case PIPE_PRIM_TRIANGLE_STRIP: - if (setup->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i++) { + /* emit first triangle vertex as first triangle vertex */ setup->triangle( setup, + get_vert(vertex_buffer, i-2, stride), get_vert(vertex_buffer, i+(i&1)-1, stride), - get_vert(vertex_buffer, i-(i&1), stride), - get_vert(vertex_buffer, i-2, stride) ); + get_vert(vertex_buffer, i-(i&1), stride) ); } } else { for (i = 2; i < nr; i++) { + /* emit last triangle vertex as last triangle vertex */ setup->triangle( setup, get_vert(vertex_buffer, i+(i&1)-2, stride), get_vert(vertex_buffer, i-(i&1)-1, stride), @@ -372,16 +406,18 @@ lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_TRIANGLE_FAN: - if (setup->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i += 1) { + /* emit first non-spoke vertex as first vertex */ setup->triangle( setup, + get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, 0, stride), - get_vert(vertex_buffer, i-1, stride) ); + get_vert(vertex_buffer, 0, stride) ); } } else { for (i = 2; i < nr; i += 1) { + /* emit last non-spoke vertex as last vertex */ setup->triangle( setup, get_vert(vertex_buffer, 0, stride), get_vert(vertex_buffer, i-1, stride), @@ -391,42 +427,86 @@ lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_QUADS: - for (i = 3; i < nr; i += 4) { - setup->triangle( setup, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); + /* GL quads don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; case PIPE_PRIM_QUAD_STRIP: - for (i = 3; i < nr; i += 2) { - setup->triangle( setup, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-0, stride) ); + /* GL quad strips don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; case PIPE_PRIM_POLYGON: /* Almost same as tri fan but the _first_ vertex specifies the flat - * shading color. Note that the first polygon vertex is passed as - * the last triangle vertex here. - * flatshade_first state makes no difference. + * shading color. */ - for (i = 2; i < nr; i += 1) { - setup->triangle( setup, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, 0, stride) ); + if (flatshade_first) { + /* emit first polygon vertex as first triangle vertex */ + for (i = 2; i < nr; i += 1) { + setup->triangle( setup, + get_vert(vertex_buffer, 0, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } + } + else { + /* emit first polygon vertex as last triangle vertex */ + for (i = 2; i < nr; i += 1) { + setup->triangle( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, 0, stride) ); + } } break; @@ -463,7 +543,7 @@ lp_setup_init_vbuf(struct lp_setup_context *setup) setup->base.map_vertices = lp_setup_map_vertices; setup->base.unmap_vertices = lp_setup_unmap_vertices; setup->base.set_primitive = lp_setup_set_primitive; - setup->base.draw = lp_setup_draw; + setup->base.draw_elements = lp_setup_draw_elements; setup->base.draw_arrays = lp_setup_draw_arrays; setup->base.release_vertices = lp_setup_release_vertices; setup->base.destroy = lp_setup_vbuf_destroy; diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h index 18143807c91..bae5de0cb35 100644 --- a/src/gallium/drivers/llvmpipe/lp_state.h +++ b/src/gallium/drivers/llvmpipe/lp_state.h @@ -63,6 +63,11 @@ struct llvmpipe_context; struct lp_fragment_shader; +/** Indexes into jit_function[] array */ +#define RAST_WHOLE 0 +#define RAST_EDGE_TEST 1 + + struct lp_fragment_shader_variant_key { struct pipe_depth_state depth; @@ -73,6 +78,7 @@ struct lp_fragment_shader_variant_key unsigned nr_cbufs:8; unsigned flatshade:1; unsigned scissor:1; + unsigned occlusion_count:1; struct { ubyte colormask; @@ -86,6 +92,8 @@ struct lp_fragment_shader_variant { struct lp_fragment_shader_variant_key key; + boolean opaque; + LLVMValueRef function[2]; lp_jit_frag_func jit_function[2]; diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 113d77ab788..2edfcb28ce6 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -163,7 +163,8 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) LP_NEW_DEPTH_STENCIL_ALPHA | LP_NEW_RASTERIZER | LP_NEW_SAMPLER | - LP_NEW_SAMPLER_VIEW)) + LP_NEW_SAMPLER_VIEW | + LP_NEW_QUERY)) llvmpipe_update_fs( llvmpipe ); if (llvmpipe->dirty & LP_NEW_BLEND_COLOR) diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 5f861d6ca4d..9ef78e6badf 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -87,7 +87,6 @@ #include "lp_bld_depth.h" #include "lp_bld_interp.h" #include "lp_context.h" -#include "lp_debug.h" #include "lp_perf.h" #include "lp_screen.h" #include "lp_setup.h" @@ -148,7 +147,8 @@ generate_depth_stencil(LLVMBuilderRef builder, LLVMValueRef stencil_refs[2], LLVMValueRef src, LLVMValueRef dst_ptr, - LLVMValueRef facing) + LLVMValueRef facing, + LLVMValueRef counter) { const struct util_format_description *format_desc; struct lp_type dst_type; @@ -195,7 +195,8 @@ generate_depth_stencil(LLVMBuilderRef builder, stencil_refs, src, dst_ptr, - facing); + facing, + counter); } @@ -400,7 +401,8 @@ generate_fs(struct llvmpipe_context *lp, LLVMValueRef c2, LLVMValueRef step0_ptr, LLVMValueRef step1_ptr, - LLVMValueRef step2_ptr) + LLVMValueRef step2_ptr, + LLVMValueRef counter) { const struct tgsi_token *tokens = shader->base.tokens; LLVMTypeRef vec_type; @@ -466,12 +468,13 @@ generate_fs(struct llvmpipe_context *lp, if (early_depth_stencil_test) generate_depth_stencil(builder, key, type, &mask, - stencil_refs, z, depth_ptr, facing); + stencil_refs, z, depth_ptr, facing, counter); lp_build_tgsi_soa(builder, tokens, type, &mask, consts_ptr, interp->pos, interp->inputs, outputs, sampler, &shader->info); + /* loop over fragment shader outputs/results */ for (attrib = 0; attrib < shader->info.num_outputs; ++attrib) { for(chan = 0; chan < NUM_CHANNELS; ++chan) { if(outputs[attrib][chan]) { @@ -513,7 +516,7 @@ generate_fs(struct llvmpipe_context *lp, if (!early_depth_stencil_test) generate_depth_stencil(builder, key, type, &mask, - stencil_refs, z, depth_ptr, facing); + stencil_refs, z, depth_ptr, facing, counter); lp_build_mask_end(&mask); @@ -528,9 +531,16 @@ generate_fs(struct llvmpipe_context *lp, /** * Generate color blending and color output. + * \param rt the render target index (to index blend, colormask state) + * \param type the pixel color type + * \param context_ptr pointer to the runtime JIT context + * \param mask execution mask (active fragment/pixel mask) + * \param src colors from the fragment shader + * \param dst_ptr the destination color buffer pointer */ static void generate_blend(const struct pipe_blend_state *blend, + unsigned rt, LLVMBuilderRef builder, struct lp_type type, LLVMValueRef context_ptr, @@ -561,6 +571,7 @@ generate_blend(const struct pipe_blend_state *blend, const_ptr = LLVMBuildBitCast(builder, const_ptr, LLVMPointerType(vec_type, 0), ""); + /* load constant blend color and colors from the dest color buffer */ for(chan = 0; chan < 4; ++chan) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0); con[chan] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), ""); @@ -571,10 +582,12 @@ generate_blend(const struct pipe_blend_state *blend, lp_build_name(dst[chan], "dst.%c", "rgba"[chan]); } - lp_build_blend_soa(builder, blend, type, src, dst, con, res); + /* do blend */ + lp_build_blend_soa(builder, blend, type, rt, src, dst, con, res); + /* store results to color buffer */ for(chan = 0; chan < 4; ++chan) { - if(blend->rt[0].colormask & (1 << chan)) { + if(blend->rt[rt].colormask & (1 << chan)) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0); lp_build_name(res[chan], "res.%c", "rgba"[chan]); res[chan] = lp_build_select(&bld, mask, res[chan], dst[chan]); @@ -587,20 +600,6 @@ generate_blend(const struct pipe_blend_state *blend, } -/** casting function to avoid compiler warnings */ -static lp_jit_frag_func -cast_voidptr_to_lp_jit_frag_func(void *p) -{ - union { - void *v; - lp_jit_frag_func f; - } tmp; - assert(sizeof(tmp.v) == sizeof(tmp.f)); - tmp.v = p; - return tmp.f; -} - - /** * Generate the runtime callable function for the whole fragment pipeline. * Note that the function which we generate operates on a block of 16 @@ -620,7 +619,7 @@ generate_fragment(struct llvmpipe_context *lp, LLVMTypeRef fs_elem_type; LLVMTypeRef fs_int_vec_type; LLVMTypeRef blend_vec_type; - LLVMTypeRef arg_types[15]; + LLVMTypeRef arg_types[16]; LLVMTypeRef func_type; LLVMTypeRef int32_vec4_type = lp_build_int32_vec4_type(); LLVMValueRef context_ptr; @@ -631,7 +630,7 @@ generate_fragment(struct llvmpipe_context *lp, LLVMValueRef dady_ptr; LLVMValueRef color_ptr_ptr; LLVMValueRef depth_ptr; - LLVMValueRef c0, c1, c2, step0_ptr, step1_ptr, step2_ptr; + LLVMValueRef c0, c1, c2, step0_ptr, step1_ptr, step2_ptr, counter = NULL; LLVMBasicBlockRef block; LLVMBuilderRef builder; LLVMValueRef x0; @@ -641,7 +640,6 @@ generate_fragment(struct llvmpipe_context *lp, LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH]; LLVMValueRef fs_out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][LP_MAX_VECTOR_LENGTH]; LLVMValueRef blend_mask; - LLVMValueRef blend_in_color[NUM_CHANNELS]; LLVMValueRef function; LLVMValueRef facing; unsigned num_fs; @@ -696,6 +694,7 @@ generate_fragment(struct llvmpipe_context *lp, arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step0 */ arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step1 */ arg_types[14] = LLVMPointerType(int32_vec4_type, 0);/* step2 */ + arg_types[15] = LLVMPointerType(LLVMInt32Type(), 0);/* counter */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); @@ -734,7 +733,7 @@ generate_fragment(struct llvmpipe_context *lp, lp_build_name(a0_ptr, "a0"); lp_build_name(dadx_ptr, "dadx"); lp_build_name(dady_ptr, "dady"); - lp_build_name(color_ptr_ptr, "color_ptr"); + lp_build_name(color_ptr_ptr, "color_ptr_ptr"); lp_build_name(depth_ptr, "depth"); lp_build_name(c0, "c0"); lp_build_name(c1, "c1"); @@ -743,6 +742,11 @@ generate_fragment(struct llvmpipe_context *lp, lp_build_name(step1_ptr, "step1"); lp_build_name(step2_ptr, "step2"); + if (key->occlusion_count) { + counter = LLVMGetParam(function, 15); + lp_build_name(counter, "counter"); + } + /* * Function body */ @@ -787,7 +791,7 @@ generate_fragment(struct llvmpipe_context *lp, facing, do_tri_test, c0, c1, c2, - step0_ptr, step1_ptr, step2_ptr); + step0_ptr, step1_ptr, step2_ptr, counter); for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) for(chan = 0; chan < NUM_CHANNELS; ++chan) @@ -801,6 +805,8 @@ generate_fragment(struct llvmpipe_context *lp, for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { LLVMValueRef color_ptr; LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), cbuf, 0); + LLVMValueRef blend_in_color[NUM_CHANNELS]; + unsigned rt; /* * Convert the fs's output color and mask to fit to the blending type. @@ -821,10 +827,14 @@ generate_fragment(struct llvmpipe_context *lp, ""); lp_build_name(color_ptr, "color_ptr%d", cbuf); + /* which blend/colormask state to use */ + rt = key->blend.independent_blend_enable ? cbuf : 0; + /* * Blending. */ generate_blend(&key->blend, + rt, builder, blend_type, context_ptr, @@ -842,7 +852,7 @@ generate_fragment(struct llvmpipe_context *lp, #ifdef DEBUG if(LLVMVerifyFunction(function, LLVMPrintMessageAction)) { if (1) - LLVMDumpValue(function); + lp_debug_dump_value(function); abort(); } #endif @@ -851,9 +861,9 @@ generate_fragment(struct llvmpipe_context *lp, if (1) LLVMRunFunctionPassManager(screen->pass, function); - if (LP_DEBUG & DEBUG_JIT) { + if (gallivm_debug & GALLIVM_DEBUG_IR) { /* Print the LLVM IR to stderr */ - LLVMDumpValue(function); + lp_debug_dump_value(function); debug_printf("\n"); } @@ -865,12 +875,84 @@ generate_fragment(struct llvmpipe_context *lp, variant->jit_function[do_tri_test] = cast_voidptr_to_lp_jit_frag_func(f); - if (LP_DEBUG & DEBUG_ASM) + if (gallivm_debug & GALLIVM_DEBUG_ASM) { lp_disassemble(f); + } } } +static void +dump_fs_variant_key(const struct lp_fragment_shader_variant_key *key) +{ + unsigned i; + + debug_printf("fs variant %p:\n", (void *) key); + + if (key->depth.enabled) { + debug_printf("depth.format = %s\n", util_format_name(key->zsbuf_format)); + debug_printf("depth.func = %s\n", util_dump_func(key->depth.func, TRUE)); + debug_printf("depth.writemask = %u\n", key->depth.writemask); + } + + for (i = 0; i < 2; ++i) { + if (key->stencil[i].enabled) { + debug_printf("stencil[%u].func = %s\n", i, util_dump_func(key->stencil[i].func, TRUE)); + debug_printf("stencil[%u].fail_op = %s\n", i, util_dump_stencil_op(key->stencil[i].fail_op, TRUE)); + debug_printf("stencil[%u].zpass_op = %s\n", i, util_dump_stencil_op(key->stencil[i].zpass_op, TRUE)); + debug_printf("stencil[%u].zfail_op = %s\n", i, util_dump_stencil_op(key->stencil[i].zfail_op, TRUE)); + debug_printf("stencil[%u].valuemask = 0x%x\n", i, key->stencil[i].valuemask); + debug_printf("stencil[%u].writemask = 0x%x\n", i, key->stencil[i].writemask); + } + } + + if (key->alpha.enabled) { + debug_printf("alpha.func = %s\n", util_dump_func(key->alpha.func, TRUE)); + debug_printf("alpha.ref_value = %f\n", key->alpha.ref_value); + } + + if (key->blend.logicop_enable) { + debug_printf("blend.logicop_func = %s\n", util_dump_logicop(key->blend.logicop_func, TRUE)); + } + else if (key->blend.rt[0].blend_enable) { + debug_printf("blend.rgb_func = %s\n", util_dump_blend_func (key->blend.rt[0].rgb_func, TRUE)); + debug_printf("blend.rgb_src_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].rgb_src_factor, TRUE)); + debug_printf("blend.rgb_dst_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].rgb_dst_factor, TRUE)); + debug_printf("blend.alpha_func = %s\n", util_dump_blend_func (key->blend.rt[0].alpha_func, TRUE)); + debug_printf("blend.alpha_src_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].alpha_src_factor, TRUE)); + debug_printf("blend.alpha_dst_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].alpha_dst_factor, TRUE)); + } + debug_printf("blend.colormask = 0x%x\n", key->blend.rt[0].colormask); + for (i = 0; i < PIPE_MAX_SAMPLERS; ++i) { + if (key->sampler[i].format) { + debug_printf("sampler[%u] = \n", i); + debug_printf(" .format = %s\n", + util_format_name(key->sampler[i].format)); + debug_printf(" .target = %s\n", + util_dump_tex_target(key->sampler[i].target, TRUE)); + debug_printf(" .pot = %u %u %u\n", + key->sampler[i].pot_width, + key->sampler[i].pot_height, + key->sampler[i].pot_depth); + debug_printf(" .wrap = %s %s %s\n", + util_dump_tex_wrap(key->sampler[i].wrap_s, TRUE), + util_dump_tex_wrap(key->sampler[i].wrap_t, TRUE), + util_dump_tex_wrap(key->sampler[i].wrap_r, TRUE)); + debug_printf(" .min_img_filter = %s\n", + util_dump_tex_filter(key->sampler[i].min_img_filter, TRUE)); + debug_printf(" .min_mip_filter = %s\n", + util_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE)); + debug_printf(" .mag_img_filter = %s\n", + util_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE)); + if (key->sampler[i].compare_mode != PIPE_TEX_COMPARE_NONE) + debug_printf(" .compare_func = %s\n", util_dump_func(key->sampler[i].compare_func, TRUE)); + debug_printf(" .normalized_coords = %u\n", key->sampler[i].normalized_coords); + } + } +} + + + static struct lp_fragment_shader_variant * generate_variant(struct llvmpipe_context *lp, struct lp_fragment_shader *shader, @@ -878,57 +960,9 @@ generate_variant(struct llvmpipe_context *lp, { struct lp_fragment_shader_variant *variant; - if (LP_DEBUG & DEBUG_JIT) { - unsigned i; - + if (gallivm_debug & GALLIVM_DEBUG_IR) { tgsi_dump(shader->base.tokens, 0); - if(key->depth.enabled) { - debug_printf("depth.format = %s\n", util_format_name(key->zsbuf_format)); - debug_printf("depth.func = %s\n", util_dump_func(key->depth.func, TRUE)); - debug_printf("depth.writemask = %u\n", key->depth.writemask); - } - if(key->alpha.enabled) { - debug_printf("alpha.func = %s\n", util_dump_func(key->alpha.func, TRUE)); - debug_printf("alpha.ref_value = %f\n", key->alpha.ref_value); - } - if(key->blend.logicop_enable) { - debug_printf("blend.logicop_func = %u\n", key->blend.logicop_func); - } - else if(key->blend.rt[0].blend_enable) { - debug_printf("blend.rgb_func = %s\n", util_dump_blend_func (key->blend.rt[0].rgb_func, TRUE)); - debug_printf("rgb_src_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].rgb_src_factor, TRUE)); - debug_printf("rgb_dst_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].rgb_dst_factor, TRUE)); - debug_printf("alpha_func = %s\n", util_dump_blend_func (key->blend.rt[0].alpha_func, TRUE)); - debug_printf("alpha_src_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].alpha_src_factor, TRUE)); - debug_printf("alpha_dst_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].alpha_dst_factor, TRUE)); - } - debug_printf("blend.colormask = 0x%x\n", key->blend.rt[0].colormask); - for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) { - if(key->sampler[i].format) { - debug_printf("sampler[%u] = \n", i); - debug_printf(" .format = %s\n", - util_format_name(key->sampler[i].format)); - debug_printf(" .target = %s\n", - util_dump_tex_target(key->sampler[i].target, TRUE)); - debug_printf(" .pot = %u %u %u\n", - key->sampler[i].pot_width, - key->sampler[i].pot_height, - key->sampler[i].pot_depth); - debug_printf(" .wrap = %s %s %s\n", - util_dump_tex_wrap(key->sampler[i].wrap_s, TRUE), - util_dump_tex_wrap(key->sampler[i].wrap_t, TRUE), - util_dump_tex_wrap(key->sampler[i].wrap_r, TRUE)); - debug_printf(" .min_img_filter = %s\n", - util_dump_tex_filter(key->sampler[i].min_img_filter, TRUE)); - debug_printf(" .min_mip_filter = %s\n", - util_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE)); - debug_printf(" .mag_img_filter = %s\n", - util_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE)); - if(key->sampler[i].compare_mode != PIPE_TEX_COMPARE_NONE) - debug_printf(" .compare_func = %s\n", util_dump_func(key->sampler[i].compare_func, TRUE)); - debug_printf(" .normalized_coords = %u\n", key->sampler[i].normalized_coords); - } - } + dump_fs_variant_key(key); } variant = CALLOC_STRUCT(lp_fragment_shader_variant); @@ -937,8 +971,20 @@ generate_variant(struct llvmpipe_context *lp, memcpy(&variant->key, key, sizeof *key); - generate_fragment(lp, shader, variant, 0); - generate_fragment(lp, shader, variant, 1); + generate_fragment(lp, shader, variant, RAST_WHOLE); + generate_fragment(lp, shader, variant, RAST_EDGE_TEST); + + /* TODO: most of these can be relaxed, in particular the colormask */ + variant->opaque = + !key->blend.logicop_enable && + !key->blend.rt[0].blend_enable && + key->blend.rt[0].colormask == 0xf && + !key->stencil[0].enabled && + !key->alpha.enabled && + !key->depth.enabled && + !key->scissor && + !shader->info.uses_kill + ? TRUE : FALSE; /* insert new variant into linked list */ variant->next = shader->variants; @@ -964,7 +1010,7 @@ llvmpipe_create_fs_state(struct pipe_context *pipe, /* we need to keep a local copy of the tokens */ shader->base.tokens = tgsi_dup_tokens(templ->tokens); - if (LP_DEBUG & DEBUG_TGSI) { + if (gallivm_debug & GALLIVM_DEBUG_TGSI) { debug_printf("llvmpipe: Create fragment shader %p:\n", (void *) shader); tgsi_dump(templ->tokens, 0); } @@ -1123,6 +1169,9 @@ make_variant_key(struct llvmpipe_context *lp, key->flatshade = lp->rasterizer->flatshade; key->scissor = lp->rasterizer->scissor; + if (lp->active_query_count) { + key->occlusion_count = TRUE; + } if (lp->framebuffer.nr_cbufs) { memcpy(&key->blend, lp->blend, sizeof key->blend); @@ -1187,7 +1236,6 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) struct lp_fragment_shader *shader = lp->fs; struct lp_fragment_shader_variant_key key; struct lp_fragment_shader_variant *variant; - boolean opaque; make_variant_key(lp, shader, &key); @@ -1212,22 +1260,10 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) LP_COUNT_ADD(nr_llvm_compiles, 2); /* emit vs. omit in/out test */ } - /* TODO: put this in the variant */ - /* TODO: most of these can be relaxed, in particular the colormask */ - opaque = !key.blend.logicop_enable && - !key.blend.rt[0].blend_enable && - key.blend.rt[0].colormask == 0xf && - !key.stencil[0].enabled && - !key.alpha.enabled && - !key.depth.enabled && - !key.scissor && - !shader->info.uses_kill - ? TRUE : FALSE; - lp_setup_set_fs_functions(lp->setup, variant->jit_function[RAST_WHOLE], variant->jit_function[RAST_EDGE_TEST], - opaque); + variant->opaque); } diff --git a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c index 622eb47ff45..afd3e0b21c9 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c +++ b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c @@ -67,8 +67,8 @@ llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, void *handle) */ if (llvmpipe->rasterizer) { lp_setup_set_triangle_state( llvmpipe->setup, - llvmpipe->rasterizer->cull_mode, - llvmpipe->rasterizer->front_winding == PIPE_WINDING_CCW, + llvmpipe->rasterizer->cull_face, + llvmpipe->rasterizer->front_ccw, llvmpipe->rasterizer->scissor, llvmpipe->rasterizer->gl_rasterization_rules); lp_setup_set_flatshade_first( llvmpipe->setup, diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c index fae7bf3fcf2..072d699666b 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_blend.c +++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c @@ -52,6 +52,19 @@ enum vector_mode typedef void (*blend_test_ptr_t)(const void *src, const void *dst, const void *con, void *res); +/** cast wrapper */ +static blend_test_ptr_t +voidptr_to_blend_test_ptr_t(void *p) +{ + union { + void *v; + blend_test_ptr_t f; + } u; + u.v = p; + return u.f; +} + + void write_tsv_header(FILE *fp) @@ -163,6 +176,7 @@ add_blend_test(LLVMModuleRef module, LLVMValueRef res_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; + const unsigned rt = 0; vec_type = lp_build_vec_type(type); @@ -188,7 +202,7 @@ add_blend_test(LLVMModuleRef module, dst = LLVMBuildLoad(builder, dst_ptr, "dst"); con = LLVMBuildLoad(builder, const_ptr, "const"); - res = lp_build_blend_aos(builder, blend, type, src, dst, con, 3); + res = lp_build_blend_aos(builder, blend, type, rt, src, dst, con, 3); lp_build_name(res, "res"); @@ -212,7 +226,7 @@ add_blend_test(LLVMModuleRef module, lp_build_name(dst[i], "dst.%c", "rgba"[i]); } - lp_build_blend_soa(builder, blend, type, src, dst, con, res); + lp_build_blend_soa(builder, blend, type, rt, src, dst, con, res); for(i = 0; i < 4; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); @@ -481,6 +495,7 @@ test_one(unsigned verbose, int64_t cycles[LP_TEST_NUM_SAMPLES]; double cycles_avg = 0.0; unsigned i, j; + void *code; if(verbose >= 1) dump_blend_type(stdout, blend, mode, type); @@ -522,10 +537,11 @@ test_one(unsigned verbose, if(verbose >= 2) LLVMDumpModule(module); - blend_test_ptr = (blend_test_ptr_t)LLVMGetPointerToGlobal(engine, func); + code = LLVMGetPointerToGlobal(engine, func); + blend_test_ptr = voidptr_to_blend_test_ptr_t(code); if(verbose >= 2) - lp_disassemble(blend_test_ptr); + lp_disassemble(code); success = TRUE; for(i = 0; i < n && success; ++i) { diff --git a/src/gallium/drivers/llvmpipe/lp_test_conv.c b/src/gallium/drivers/llvmpipe/lp_test_conv.c index 958cc40538e..254f0daea3b 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_conv.c +++ b/src/gallium/drivers/llvmpipe/lp_test_conv.c @@ -43,6 +43,17 @@ typedef void (*conv_test_ptr_t)(const void *src, const void *dst); +/** cast wrapper */ +static conv_test_ptr_t +voidptr_to_conv_test_ptr_t(void *p) +{ + union { + void *v; + conv_test_ptr_t f; + } u; + u.v = p; + return u.f; +} void write_tsv_header(FILE *fp) @@ -164,6 +175,7 @@ test_one(unsigned verbose, unsigned num_dsts; double eps; unsigned i, j; + void *code; if(verbose >= 1) dump_conv_types(stdout, src_type, dst_type); @@ -221,10 +233,11 @@ test_one(unsigned verbose, if(verbose >= 2) LLVMDumpModule(module); - conv_test_ptr = (conv_test_ptr_t)LLVMGetPointerToGlobal(engine, func); + code = LLVMGetPointerToGlobal(engine, func); + conv_test_ptr = voidptr_to_conv_test_ptr_t(code); if(verbose >= 2) - lp_disassemble(conv_test_ptr); + lp_disassemble(code); success = TRUE; for(i = 0; i < n && success; ++i) { @@ -384,7 +397,7 @@ test_all(unsigned verbose, FILE *fp) { const struct lp_type *src_type; const struct lp_type *dst_type; - bool success = TRUE; + boolean success = TRUE; for(src_type = conv_types; src_type < &conv_types[num_types]; ++src_type) { for(dst_type = conv_types; dst_type < &conv_types[num_types]; ++dst_type) { @@ -411,7 +424,7 @@ test_some(unsigned verbose, FILE *fp, unsigned long n) const struct lp_type *src_type; const struct lp_type *dst_type; unsigned long i; - bool success = TRUE; + boolean success = TRUE; for(i = 0; i < n; ++i) { src_type = &conv_types[rand() % num_types]; diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c index fbac815d107..267f1487bb8 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_format.c +++ b/src/gallium/drivers/llvmpipe/lp_test_format.c @@ -73,6 +73,19 @@ typedef void (*fetch_ptr_t)(float *, const void *packed, unsigned i, unsigned j); +/** cast wrapper to avoid warnings */ +static fetch_ptr_t +void_to_fetch_ptr_t(void *p) +{ + union { + void *v; + fetch_ptr_t f; + } u; + u.v = p; + return u.f; +} + + static LLVMValueRef add_fetch_rgba_test(LLVMModuleRef lp_build_module, @@ -125,7 +138,7 @@ test_format(unsigned verbose, FILE *fp, fetch_ptr_t fetch_ptr; float unpacked[4]; boolean success; - unsigned i; + unsigned i, j, k; fetch = add_fetch_rgba_test(lp_build_module, desc); @@ -149,31 +162,39 @@ test_format(unsigned verbose, FILE *fp, (void)pass; #endif - fetch_ptr = (fetch_ptr_t) LLVMGetPointerToGlobal(lp_build_engine, fetch); + fetch_ptr = void_to_fetch_ptr_t(LLVMGetPointerToGlobal(lp_build_engine, fetch)); - memset(unpacked, 0, sizeof unpacked); + for (i = 0; i < desc->block.height; ++i) { + for (j = 0; j < desc->block.width; ++j) { - fetch_ptr(unpacked, test->packed, 0, 0); + memset(unpacked, 0, sizeof unpacked); - success = TRUE; - for(i = 0; i < 4; ++i) - if (fabs((float)test->unpacked[0][0][i] - unpacked[i]) > FLT_EPSILON) - success = FALSE; + fetch_ptr(unpacked, test->packed, j, i); - if (!success) { - printf("FAILED\n"); - printf(" Packed: %02x %02x %02x %02x\n", - test->packed[0], test->packed[1], test->packed[2], test->packed[3]); - printf(" Unpacked: %f %f %f %f obtained\n", - unpacked[0], unpacked[1], unpacked[2], unpacked[3]); - printf(" %f %f %f %f expected\n", - test->unpacked[0][0][0], - test->unpacked[0][0][1], - test->unpacked[0][0][2], - test->unpacked[0][0][3]); - LLVMDumpValue(fetch); + success = TRUE; + for(k = 0; k < 4; ++k) + if (fabs((float)test->unpacked[i][j][k] - unpacked[k]) > FLT_EPSILON) + success = FALSE; + + if (!success) { + printf("FAILED\n"); + printf(" Packed: %02x %02x %02x %02x\n", + test->packed[0], test->packed[1], test->packed[2], test->packed[3]); + printf(" Unpacked (%u,%u): %f %f %f %f obtained\n", + j, i, + unpacked[0], unpacked[1], unpacked[2], unpacked[3]); + printf(" %f %f %f %f expected\n", + test->unpacked[i][j][0], + test->unpacked[i][j][1], + test->unpacked[i][j][2], + test->unpacked[i][j][3]); + } + } } + if (!success) + LLVMDumpValue(fetch); + LLVMFreeMachineCodeForFunction(lp_build_engine, fetch); LLVMDeleteFunction(fetch); @@ -193,20 +214,23 @@ test_one(unsigned verbose, FILE *fp, const struct util_format_description *format_desc) { unsigned i; - bool success = TRUE; - - printf("Testing %s ...\n", - format_desc->name); + boolean first = TRUE; + boolean success = TRUE; for (i = 0; i < util_format_nr_test_cases; ++i) { const struct util_format_test_case *test = &util_format_test_cases[i]; if (test->format == format_desc->format) { + if (first) { + printf("Testing %s ...\n", + format_desc->name); + first = FALSE; + } + if (!test_format(verbose, fp, format_desc, test)) { success = FALSE; } - } } @@ -218,7 +242,7 @@ boolean test_all(unsigned verbose, FILE *fp) { enum pipe_format format; - bool success = TRUE; + boolean success = TRUE; for (format = 1; format < PIPE_FORMAT_COUNT; ++format) { const struct util_format_description *format_desc; @@ -232,9 +256,7 @@ test_all(unsigned verbose, FILE *fp) * TODO: test more */ - if (format_desc->block.width != 1 || - format_desc->block.height != 1 || - format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { + if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { continue; } diff --git a/src/gallium/drivers/llvmpipe/lp_test_printf.c b/src/gallium/drivers/llvmpipe/lp_test_printf.c index e5e5925012a..13485c37748 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_printf.c +++ b/src/gallium/drivers/llvmpipe/lp_test_printf.c @@ -41,6 +41,7 @@ struct printf_test_case { + int foo; }; void @@ -57,6 +58,19 @@ write_tsv_header(FILE *fp) typedef void (*test_printf_t)(int i); +/** cast wrapper */ +static test_printf_t +voidptr_to_test_printf_t(void *p) +{ + union { + void *v; + test_printf_t f; + } u; + u.v = p; + return u.f; +} + + static LLVMValueRef add_printf_test(LLVMModuleRef module) { @@ -91,6 +105,7 @@ test_printf(unsigned verbose, FILE *fp, const struct printf_test_case *testcase) float unpacked[4]; unsigned packed; boolean success = TRUE; + void *code; module = LLVMModuleCreateWithName("test"); @@ -124,7 +139,8 @@ test_printf(unsigned verbose, FILE *fp, const struct printf_test_case *testcase) (void)pass; #endif - test_printf = (test_printf_t)LLVMGetPointerToGlobal(engine, test); + code = LLVMGetPointerToGlobal(engine, test); + test_printf = voidptr_to_test_printf_t(code); memset(unpacked, 0, sizeof unpacked); packed = 0; @@ -147,7 +163,7 @@ test_printf(unsigned verbose, FILE *fp, const struct printf_test_case *testcase) boolean test_all(unsigned verbose, FILE *fp) { - bool success = TRUE; + boolean success = TRUE; test_printf(verbose, fp, NULL); diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c b/src/gallium/drivers/llvmpipe/lp_tex_sample.c index d3a9d39f616..65208dd5d5c 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.c @@ -87,7 +87,7 @@ struct lp_llvm_sampler_soa * @sa http://llvm.org/docs/GetElementPtr.html */ static LLVMValueRef -lp_llvm_texture_member(struct lp_sampler_dynamic_state *base, +lp_llvm_texture_member(const struct lp_sampler_dynamic_state *base, LLVMBuilderRef builder, unsigned unit, unsigned member_index, @@ -135,7 +135,7 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base, */ #define LP_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \ static LLVMValueRef \ - lp_llvm_texture_##_name( struct lp_sampler_dynamic_state *base, \ + lp_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \ LLVMBuilderRef builder, \ unsigned unit) \ { \ @@ -164,7 +164,7 @@ lp_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler) * The 'texel' parameter returns four vectors corresponding to R, G, B, A. */ static void -lp_llvm_sampler_soa_emit_fetch_texel(struct lp_build_sampler_soa *base, +lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, LLVMBuilderRef builder, struct lp_type type, unsigned unit, diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 2f41d620c8a..4eed687ac71 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -39,6 +39,7 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_simple_list.h" #include "util/u_transfer.h" #include "lp_context.h" @@ -51,6 +52,11 @@ #include "state_tracker/sw_winsys.h" +#ifdef DEBUG +static struct llvmpipe_resource resource_list; +#endif + + static INLINE boolean resource_is_texture(const struct pipe_resource *resource) { @@ -107,32 +113,55 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen, assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS); for (level = 0; level <= pt->last_level; level++) { - const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE; - const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE; - unsigned nblocksx, num_slices; - - if (lpr->base.target == PIPE_TEXTURE_CUBE) - num_slices = 6; - else if (lpr->base.target == PIPE_TEXTURE_3D) - num_slices = depth; - else - num_slices = 1; - - /* Allocate storage for whole quads. This is particularly important - * for depth surfaces, which are currently stored in a swizzled format. - */ - nblocksx = util_format_get_nblocksx(pt->format, align(width, TILE_SIZE)); - lpr->row_stride[level] = - align(nblocksx * util_format_get_blocksize(pt->format), 16); + /* Row stride and image stride (for linear layout) */ + { + unsigned alignment, nblocksx, nblocksy, block_size; + + /* For non-compressed formats we need to align the texture size + * to the tile size to facilitate render-to-texture. + */ + if (util_format_is_compressed(pt->format)) + alignment = 1; + else + alignment = TILE_SIZE; + + nblocksx = util_format_get_nblocksx(pt->format, + align(width, alignment)); + nblocksy = util_format_get_nblocksy(pt->format, + align(height, alignment)); + block_size = util_format_get_blocksize(pt->format); - lpr->img_stride[level] = lpr->row_stride[level] * align(height, TILE_SIZE); + lpr->row_stride[level] = align(nblocksx * block_size, 16); - lpr->tiles_per_row[level] = width_t; - lpr->tiles_per_image[level] = width_t * height_t; - lpr->num_slices_faces[level] = num_slices; - lpr->layout[level] = alloc_layout_array(num_slices, width, height); + lpr->img_stride[level] = lpr->row_stride[level] * nblocksy; + } + /* Size of the image in tiles (for tiled layout) */ + { + const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE; + const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE; + lpr->tiles_per_row[level] = width_t; + lpr->tiles_per_image[level] = width_t * height_t; + } + + /* Number of 3D image slices or cube faces */ + { + unsigned num_slices; + + if (lpr->base.target == PIPE_TEXTURE_CUBE) + num_slices = 6; + else if (lpr->base.target == PIPE_TEXTURE_3D) + num_slices = depth; + else + num_slices = 1; + + lpr->num_slices_faces[level] = num_slices; + + lpr->layout[level] = alloc_layout_array(num_slices, width, height); + } + + /* Compute size of next mipmap level */ width = u_minify(width, 1); height = u_minify(height, 1); depth = u_minify(depth, 1); @@ -222,6 +251,10 @@ llvmpipe_resource_create(struct pipe_screen *_screen, lpr->id = id_counter++; +#ifdef DEBUG + insert_at_tail(&resource_list, lpr); +#endif + return &lpr->base; fail: @@ -280,6 +313,11 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen, align_free(lpr->data); } +#ifdef DEBUG + if (lpr->next) + remove_from_list(lpr); +#endif + FREE(lpr); } @@ -450,7 +488,7 @@ static struct pipe_surface * llvmpipe_get_tex_surface(struct pipe_screen *screen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, - enum lp_texture_usage usage) + unsigned usage) { struct pipe_surface *ps; @@ -698,11 +736,8 @@ tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level, return buffer_size; } else { - const enum pipe_format format = lpr->base.format; - const unsigned nblocksy = - util_format_get_nblocksy(format, align(height, TILE_SIZE)); - const unsigned buffer_size = nblocksy * lpr->row_stride[level]; - return buffer_size; + /* we already computed this */ + return lpr->img_stride[level]; } } @@ -1188,9 +1223,43 @@ llvmpipe_resource_size(const struct pipe_resource *resource) } +#ifdef DEBUG +void +llvmpipe_print_resources(void) +{ + struct llvmpipe_resource *lpr; + unsigned n = 0, total = 0; + + debug_printf("LLVMPIPE: current resources:\n"); + foreach(lpr, &resource_list) { + unsigned size = llvmpipe_resource_size(&lpr->base); + debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n", + lpr->id, (void *) lpr, + lpr->base.width0, lpr->base.height0, lpr->base.depth0, + size, lpr->base.reference.count); + total += size; + n++; + } + debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total); +} +#endif + + void llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen) { +#ifdef DEBUG + /* init linked list for tracking resources */ + { + static boolean first_call = TRUE; + if (first_call) { + memset(&resource_list, 0, sizeof(resource_list)); + make_empty_list(&resource_list); + first_call = FALSE; + } + } +#endif + screen->resource_create = llvmpipe_resource_create; screen->resource_destroy = llvmpipe_resource_destroy; screen->resource_from_handle = llvmpipe_resource_from_handle; diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h index a8d08d6247f..503b6a19a8d 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.h +++ b/src/gallium/drivers/llvmpipe/lp_texture.h @@ -119,6 +119,11 @@ struct llvmpipe_resource unsigned timestamp; unsigned id; /**< temporary, for debugging */ + +#ifdef DEBUG + /** for linked list */ + struct llvmpipe_resource *prev, *next; +#endif }; @@ -220,6 +225,10 @@ llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr, extern void +llvmpipe_print_resources(void); + + +extern void llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen); extern void diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c index 89d5ffa8aa3..60bdd7276aa 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.c +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -5,6 +5,7 @@ #include "util/u_memory.h" #include "util/u_inlines.h" #include "util/u_format.h" +#include "util/u_format_s3tc.h" #include <stdio.h> #include <errno.h> @@ -246,6 +247,8 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) pscreen->fence_signalled = nouveau_screen_fence_signalled; pscreen->fence_finish = nouveau_screen_fence_finish; + util_format_s3tc_init(); + return 0; } diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index 0156ff95ff9..97f938e6980 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -4208,9 +4208,12 @@ static void nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) { struct nouveau_channel *chan = nv50->screen->base.channel; + struct nouveau_grobj *tesla = nv50->screen->tesla; struct nv50_program_exec *e; uint32_t *up, i; boolean upload = FALSE; + unsigned offset; + int width; if (!p->bo) { nouveau_bo_new(chan->device, NOUVEAU_BO_VRAM, 0x100, @@ -4267,10 +4270,22 @@ nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) NOUVEAU_ERR("0x%08x\n", e->inst[1]); } #endif - nv50_upload_sifc(nv50, p->bo, 0, NOUVEAU_BO_VRAM, - NV50_2D_DST_FORMAT_R8_UNORM, 65536, 1, 262144, - up, NV50_2D_SIFC_FORMAT_R8_UNORM, 0, - 0, 0, p->exec_size * 4, 1, 1); + + /* SIFC_HEIGHT/SIFC_WIDTH of 65536 do not work, and are not reported + * as data error either. hw bug ? */ +#define SIFC_MAX_WIDTH (65536 - 256) + offset = 0; + width = p->exec_size * 4; + while (width > 0) { + nv50_upload_sifc(nv50, p->bo, offset, NOUVEAU_BO_VRAM, + NV50_2D_DST_FORMAT_R8_UNORM, 65536, 1, 262144, + &up[offset / 4], NV50_2D_SIFC_FORMAT_R8_UNORM, + 0, 0, 0, MIN2(SIFC_MAX_WIDTH, width), 1, 1); + width -= SIFC_MAX_WIDTH; + offset += SIFC_MAX_WIDTH; + } + BEGIN_RING(chan, tesla, NV50TCL_CODE_CB_FLUSH, 1); + OUT_RING (chan, 0); FREE(up); } diff --git a/src/gallium/drivers/nv50/nv50_push.c b/src/gallium/drivers/nv50/nv50_push.c index 244242b8434..c3ac8041462 100644 --- a/src/gallium/drivers/nv50/nv50_push.c +++ b/src/gallium/drivers/nv50/nv50_push.c @@ -108,7 +108,7 @@ emit_vertex(struct push_context *ctx, unsigned n) int i; if (ctx->edgeflag_attr < 16) { - float *edgeflag = ctx->attr[ctx->edgeflag_attr].map + + float *edgeflag = (uint8_t *)ctx->attr[ctx->edgeflag_attr].map + ctx->attr[ctx->edgeflag_attr].stride * n; if (*edgeflag != ctx->edgeflag) { @@ -120,7 +120,8 @@ emit_vertex(struct push_context *ctx, unsigned n) BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, ctx->vtx_size); for (i = 0; i < ctx->attr_nr; i++) - ctx->attr[i].push(chan, ctx->attr[i].map + ctx->attr[i].stride * n); + ctx->attr[i].push(chan, + (uint8_t *)ctx->attr[i].map + ctx->attr[i].stride * n); } static void @@ -243,14 +244,14 @@ nv50_push_elements_instanced(struct pipe_context *pipe, assert(bo->map); return; } - ctx.attr[n].map = bo->map + vb->buffer_offset + ve->src_offset; + ctx.attr[n].map = (uint8_t *)bo->map + vb->buffer_offset + ve->src_offset; nouveau_bo_unmap(bo); ctx.attr[n].stride = vb->stride; ctx.attr[n].divisor = ve->instance_divisor; if (ctx.attr[n].divisor) { ctx.attr[n].step = i_start % ve->instance_divisor; - ctx.attr[n].map += i_start * vb->stride; + ctx.attr[n].map = (uint8_t *)ctx.attr[n].map + i_start * vb->stride; } size = util_format_get_component_bits(ve->src_format, @@ -331,7 +332,7 @@ nv50_push_elements_instanced(struct pipe_context *pipe, ctx.attr[i].divisor != ++ctx.attr[i].step) continue; ctx.attr[i].step = 0; - ctx.attr[i].map += ctx.attr[i].stride; + ctx.attr[i].map = (uint8_t *)ctx.attr[i].map + ctx.attr[i].stride; } u_split_prim_init(&s, mode, start, count); diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index a8cb1e25d81..2c0caada366 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -20,6 +20,7 @@ * SOFTWARE. */ +#include "util/u_format_s3tc.h" #include "pipe/p_screen.h" #include "nv50_context.h" @@ -64,6 +65,17 @@ nv50_screen_is_format_supported(struct pipe_screen *pscreen, break; } } else { + if (tex_usage & PIPE_BIND_SAMPLER_VIEW) { + switch (format) { + case PIPE_FORMAT_DXT1_RGB: + case PIPE_FORMAT_DXT1_RGBA: + case PIPE_FORMAT_DXT3_RGBA: + case PIPE_FORMAT_DXT5_RGBA: + return util_format_s3tc_enabled; + default: + break; + } + } switch (format) { case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: @@ -76,10 +88,6 @@ nv50_screen_is_format_supported(struct pipe_screen *pscreen, case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8A8_UNORM: - case PIPE_FORMAT_DXT1_RGB: - case PIPE_FORMAT_DXT1_RGBA: - case PIPE_FORMAT_DXT3_RGBA: - case PIPE_FORMAT_DXT5_RGBA: case PIPE_FORMAT_S8_USCALED_Z24_UNORM: case PIPE_FORMAT_Z24_UNORM_S8_USCALED: case PIPE_FORMAT_Z32_FLOAT: @@ -98,7 +106,7 @@ nv50_screen_is_format_supported(struct pipe_screen *pscreen, } static int -nv50_screen_get_param(struct pipe_screen *pscreen, int param) +nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: @@ -121,6 +129,8 @@ nv50_screen_get_param(struct pipe_screen *pscreen, int param) return 8; case PIPE_CAP_OCCLUSION_QUERY: return 1; + case PIPE_CAP_TIMER_QUERY: + return 0; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: @@ -146,6 +156,34 @@ nv50_screen_get_param(struct pipe_screen *pscreen, int param) case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 0; + case PIPE_CAP_MAX_VS_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_ALU_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_ALU_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_TEX_INDIRECTIONS: + case PIPE_CAP_MAX_FS_TEX_INDIRECTIONS: /* arbitrary limit */ + return 16384; + case PIPE_CAP_MAX_VS_CONTROL_FLOW_DEPTH: + case PIPE_CAP_MAX_FS_CONTROL_FLOW_DEPTH: /* need stack bo */ + return 4; + case PIPE_CAP_MAX_VS_INPUTS: + return 16; + case PIPE_CAP_MAX_FS_INPUTS: /* 128 / 4 with GP */ + return 64 / 4; + case PIPE_CAP_MAX_VS_CONSTS: + case PIPE_CAP_MAX_FS_CONSTS: + return 65536 / 16; + case PIPE_CAP_MAX_VS_ADDRS: + case PIPE_CAP_MAX_FS_ADDRS: /* no spilling atm */ + return 1; + case PIPE_CAP_MAX_VS_PREDS: + case PIPE_CAP_MAX_FS_PREDS: /* not yet handled */ + return 0; + case PIPE_CAP_MAX_VS_TEMPS: + case PIPE_CAP_MAX_FS_TEMPS: /* no spilling atm */ + return 128 / 4; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; @@ -153,7 +191,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, int param) } static float -nv50_screen_get_paramf(struct pipe_screen *pscreen, int param) +nv50_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index cf4105bcb77..f8bff764f27 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -345,7 +345,7 @@ nv50_rasterizer_state_create(struct pipe_context *pipe, CALLOC_STRUCT(nv50_rasterizer_stateobj); /*XXX: ignored - * - light_twosize + * - light_twoside * - point_smooth * - multisample * - point_sprite / sprite_coord_mode @@ -385,72 +385,44 @@ nv50_rasterizer_state_create(struct pipe_context *pipe, so_data (so, cso->point_quad_rasterization ? 1 : 0); so_method(so, tesla, NV50TCL_POLYGON_MODE_FRONT, 3); - if (cso->front_winding == PIPE_WINDING_CCW) { - so_data(so, nvgl_polygon_mode(cso->fill_ccw)); - so_data(so, nvgl_polygon_mode(cso->fill_cw)); - } else { - so_data(so, nvgl_polygon_mode(cso->fill_cw)); - so_data(so, nvgl_polygon_mode(cso->fill_ccw)); - } + so_data(so, nvgl_polygon_mode(cso->fill_front)); + so_data(so, nvgl_polygon_mode(cso->fill_back)); so_data(so, cso->poly_smooth ? 1 : 0); so_method(so, tesla, NV50TCL_CULL_FACE_ENABLE, 3); - so_data (so, cso->cull_mode != PIPE_WINDING_NONE); - if (cso->front_winding == PIPE_WINDING_CCW) { + so_data (so, cso->cull_face != PIPE_FACE_NONE); + if (cso->front_ccw) { so_data(so, NV50TCL_FRONT_FACE_CCW); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - so_data(so, NV50TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_CW: - so_data(so, NV50TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_BOTH: - so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - so_data(so, NV50TCL_CULL_FACE_BACK); - break; - } - } else { + } + else { so_data(so, NV50TCL_FRONT_FACE_CW); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - so_data(so, NV50TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_CW: - so_data(so, NV50TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_BOTH: - so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - so_data(so, NV50TCL_CULL_FACE_BACK); - break; - } + } + switch (cso->cull_face) { + case PIPE_FACE_FRONT: + so_data(so, NV50TCL_CULL_FACE_FRONT); + break; + case PIPE_FACE_BACK: + so_data(so, NV50TCL_CULL_FACE_BACK); + break; + case PIPE_FACE_FRONT_AND_BACK: + so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK); + break; + default: + so_data(so, NV50TCL_CULL_FACE_BACK); + break; } so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_ENABLE, 1); so_data (so, cso->poly_stipple_enable ? 1 : 0); so_method(so, tesla, NV50TCL_POLYGON_OFFSET_POINT_ENABLE, 3); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) - so_data(so, 1); - else - so_data(so, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) - so_data(so, 1); - else - so_data(so, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) - so_data(so, 1); - else - so_data(so, 0); + so_data(so, cso->offset_point); + so_data(so, cso->offset_line); + so_data(so, cso->offset_tri); - if (cso->offset_cw || cso->offset_ccw) { + if (cso->offset_point || + cso->offset_line || + cso->offset_tri) { so_method(so, tesla, NV50TCL_POLYGON_OFFSET_FACTOR, 1); so_data (so, fui(cso->offset_scale)); so_method(so, tesla, NV50TCL_POLYGON_OFFSET_UNITS, 1); diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c index c5581a6f9d0..f973cf24b98 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nv50/nv50_transfer.c @@ -274,7 +274,6 @@ nv50_upload_sifc(struct nv50_context *nv50, { struct nouveau_channel *chan = nv50->screen->base.channel; struct nouveau_grobj *eng2d = nv50->screen->eng2d; - struct nouveau_grobj *tesla = nv50->screen->tesla; unsigned line_dwords = (w * cpp + 3) / 4; reloc |= NOUVEAU_BO_WR; @@ -346,7 +345,4 @@ nv50_upload_sifc(struct nv50_context *nv50, src = (uint8_t *) src + src_pitch; } - - BEGIN_RING(chan, tesla, NV50TCL_CODE_CB_FLUSH, 1); - OUT_RING (chan, 0); } diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c index 1786af776aa..7e534a0c738 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.c +++ b/src/gallium/drivers/nvfx/nvfx_screen.c @@ -1,5 +1,6 @@ #include "pipe/p_screen.h" #include "pipe/p_state.h" +#include "util/u_format_s3tc.h" #include "util/u_simple_screen.h" #include "nouveau/nouveau_screen.h" @@ -29,7 +30,7 @@ struct nouveau_winsys { #define NV6X_GRCLASS4497_CHIPSETS 0x00000088 static int -nvfx_screen_get_param(struct pipe_screen *pscreen, int param) +nvfx_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) { struct nvfx_screen *screen = nvfx_screen(pscreen); @@ -51,6 +52,8 @@ nvfx_screen_get_param(struct pipe_screen *pscreen, int param) return screen->is_nv4x ? 4 : 2; case PIPE_CAP_OCCLUSION_QUERY: return 1; + case PIPE_CAP_TIMER_QUERY: + return 0; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: @@ -83,6 +86,45 @@ nvfx_screen_get_param(struct pipe_screen *pscreen, int param) case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 0; + case PIPE_CAP_MAX_FS_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_ALU_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_TEX_INDIRECTIONS: + return 4096; + case PIPE_CAP_MAX_FS_CONTROL_FLOW_DEPTH: + /* FIXME: is it the dynamic (nv30:0/nv40:24) or the static + value (nv30:0/nv40:4) ? */ + return screen->is_nv4x ? 4 : 0; + case PIPE_CAP_MAX_FS_INPUTS: + return 10; + case PIPE_CAP_MAX_FS_CONSTS: + return screen->is_nv4x ? 224 : 32; + case PIPE_CAP_MAX_FS_TEMPS: + return 32; + case PIPE_CAP_MAX_FS_ADDRS: + return screen->is_nv4x ? 1 : 0; + case PIPE_CAP_MAX_FS_PREDS: + return screen->is_nv4x ? 1 : 0; + case PIPE_CAP_MAX_VS_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_ALU_INSTRUCTIONS: + return screen->is_nv4x ? 512 : 256; + case PIPE_CAP_MAX_VS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_TEX_INDIRECTIONS: + return screen->is_nv4x ? 512 : 0; + case PIPE_CAP_MAX_VS_CONTROL_FLOW_DEPTH: + /* FIXME: is it the dynamic (nv30:24/nv40:24) or the static + value (nv30:1/nv40:4) ? */ + return screen->is_nv4x ? 4 : 1; + case PIPE_CAP_MAX_VS_INPUTS: + return 16; + case PIPE_CAP_MAX_VS_CONSTS: + return 256; + case PIPE_CAP_MAX_VS_TEMPS: + return screen->is_nv4x ? 32 : 13; + case PIPE_CAP_MAX_VS_ADDRS: + return 2; + case PIPE_CAP_MAX_VS_PREDS: + return screen->is_nv4x ? 1 : 0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; @@ -90,7 +132,7 @@ nvfx_screen_get_param(struct pipe_screen *pscreen, int param) } static float -nvfx_screen_get_paramf(struct pipe_screen *pscreen, int param) +nvfx_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_cap param) { struct nvfx_screen *screen = nvfx_screen(pscreen); @@ -149,6 +191,17 @@ nvfx_screen_surface_format_supported(struct pipe_screen *pscreen, } } else { switch (format) { + if (tex_usage & PIPE_BIND_SAMPLER_VIEW) { + switch (format) { + case PIPE_FORMAT_DXT1_RGB: + case PIPE_FORMAT_DXT1_RGBA: + case PIPE_FORMAT_DXT3_RGBA: + case PIPE_FORMAT_DXT5_RGBA: + return util_format_s3tc_enabled; + default: + break; + } + } case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: case PIPE_FORMAT_B5G5R5A1_UNORM: @@ -160,10 +213,6 @@ nvfx_screen_surface_format_supported(struct pipe_screen *pscreen, case PIPE_FORMAT_L8A8_UNORM: case PIPE_FORMAT_Z16_UNORM: case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - case PIPE_FORMAT_DXT1_RGB: - case PIPE_FORMAT_DXT1_RGBA: - case PIPE_FORMAT_DXT3_RGBA: - case PIPE_FORMAT_DXT5_RGBA: return TRUE; /* TODO: does nv30 support this? */ case PIPE_FORMAT_R16_SNORM: diff --git a/src/gallium/drivers/nvfx/nvfx_state.c b/src/gallium/drivers/nvfx/nvfx_state.c index 3c566808d03..30322d46d93 100644 --- a/src/gallium/drivers/nvfx/nvfx_state.c +++ b/src/gallium/drivers/nvfx/nvfx_state.c @@ -216,66 +216,39 @@ nvfx_rasterizer_state_create(struct pipe_context *pipe, sb_data(sb, fui(cso->point_size)); sb_method(sb, NV34TCL_POLYGON_MODE_FRONT, 6); - if (cso->front_winding == PIPE_WINDING_CCW) { - sb_data(sb, nvgl_polygon_mode(cso->fill_ccw)); - sb_data(sb, nvgl_polygon_mode(cso->fill_cw)); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - sb_data(sb, NV34TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_CW: - sb_data(sb, NV34TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_BOTH: - sb_data(sb, NV34TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - sb_data(sb, NV34TCL_CULL_FACE_BACK); - break; - } + sb_data(sb, nvgl_polygon_mode(cso->fill_front)); + sb_data(sb, nvgl_polygon_mode(cso->fill_back)); + switch (cso->cull_face) { + case PIPE_FACE_FRONT: + sb_data(sb, NV34TCL_CULL_FACE_FRONT); + break; + case PIPE_FACE_BACK: + sb_data(sb, NV34TCL_CULL_FACE_BACK); + break; + case PIPE_FACE_FRONT_AND_BACK: + sb_data(sb, NV34TCL_CULL_FACE_FRONT_AND_BACK); + break; + default: + sb_data(sb, NV34TCL_CULL_FACE_BACK); + break; + } + if (cso->front_ccw) { sb_data(sb, NV34TCL_FRONT_FACE_CCW); } else { - sb_data(sb, nvgl_polygon_mode(cso->fill_cw)); - sb_data(sb, nvgl_polygon_mode(cso->fill_ccw)); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - sb_data(sb, NV34TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_CW: - sb_data(sb, NV34TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_BOTH: - sb_data(sb, NV34TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - sb_data(sb, NV34TCL_CULL_FACE_BACK); - break; - } sb_data(sb, NV34TCL_FRONT_FACE_CW); } sb_data(sb, cso->poly_smooth ? 1 : 0); - sb_data(sb, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0); + sb_data(sb, (cso->cull_face != PIPE_FACE_NONE) ? 1 : 0); sb_method(sb, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); sb_data(sb, cso->poly_stipple_enable ? 1 : 0); sb_method(sb, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) - sb_data(sb, 1); - else - sb_data(sb, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) - sb_data(sb, 1); - else - sb_data(sb, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) - sb_data(sb, 1); - else - sb_data(sb, 0); - if (cso->offset_cw || cso->offset_ccw) { + sb_data(sb, cso->offset_point); + sb_data(sb, cso->offset_line); + sb_data(sb, cso->offset_tri); + + if (cso->offset_point || cso->offset_line || cso->offset_tri) { sb_method(sb, NV34TCL_POLYGON_OFFSET_FACTOR, 2); sb_data(sb, fui(cso->offset_scale)); sb_data(sb, fui(cso->offset_units * 2)); diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index b3ef97fa52b..f771e10c64e 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -80,6 +80,9 @@ static void r300_destroy_context(struct pipe_context* context) FREE(r300->ztop_state.state); FREE(r300->fs_constants.state); FREE(r300->vs_constants.state); + if (!r300->screen->caps.has_tcl) { + FREE(r300->vertex_stream_state.state); + } FREE(r300); } @@ -151,6 +154,16 @@ static void r300_setup_atoms(struct r300_context* r300) r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state); r300->fs_constants.state = CALLOC_STRUCT(r300_constant_buffer); r300->vs_constants.state = CALLOC_STRUCT(r300_constant_buffer); + if (!r300->screen->caps.has_tcl) { + r300->vertex_stream_state.state = CALLOC_STRUCT(r300_vertex_stream_state); + } + + /* Some non-CSO atoms don't use the state pointer. */ + r300->invariant_state.allow_null_state = TRUE; + r300->fs_rc_constant_state.allow_null_state = TRUE; + r300->pvs_flush.allow_null_state = TRUE; + r300->query_start.allow_null_state = TRUE; + r300->texture_cache_inval.allow_null_state = TRUE; } struct pipe_context* r300_create_context(struct pipe_screen* screen, @@ -201,9 +214,9 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300)); /* Enable Draw's clipping. */ draw_set_driver_clipping(r300->draw, FALSE); - /* Force Draw to never do viewport transform, since we can do - * transform in hardware, always. */ - draw_set_viewport_state(r300->draw, &r300_viewport_identity); + /* Disable converting points/lines to triangles. */ + draw_wide_line_threshold(r300->draw, 10000000.f); + draw_wide_point_threshold(r300->draw, 10000000.f); } r300_setup_atoms(r300); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index e9c8fcdc157..e44906d0099 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -55,6 +55,8 @@ struct r300_atom { unsigned size; /* Whether this atom should be emitted. */ boolean dirty; + /* Whether this atom may be emitted with state == NULL. */ + boolean allow_null_state; }; struct r300_blend_state { @@ -88,12 +90,15 @@ struct r300_dsa_state { }; struct r300_rs_state { - /* Draw-specific rasterizer state */ + /* Original rasterizer state. */ struct pipe_rasterizer_state rs; + /* Draw-specific rasterizer state. */ + struct pipe_rasterizer_state rs_draw; uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */ uint32_t antialiasing_config; /* R300_GB_AA_CONFIG: 0x4020 */ uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */ + uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */ uint32_t line_control; /* R300_GA_LINE_CNTL: 0x4234 */ float depth_scale; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */ /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */ @@ -151,6 +156,10 @@ struct r300_texture_format_state { struct r300_sampler_view { struct pipe_sampler_view base; + /* Swizzles in the UTIL_FORMAT_SWIZZLE_* representation, + * derived from base. */ + unsigned char swizzle[4]; + /* Copy of r300_texture::texture_format_state with format-specific bits * added. */ struct r300_texture_format_state format; @@ -166,6 +175,13 @@ struct r300_texture_fb_state { uint32_t zb_format; /* R300_ZB_FORMAT */ }; +struct r300_texture_sampler_state { + struct r300_texture_format_state format; + uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ + uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */ + uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ +}; + struct r300_textures_state { /* Textures. */ struct r300_sampler_view *sampler_views[16]; @@ -177,12 +193,7 @@ struct r300_textures_state { /* This is the merge of the texture and sampler states. */ unsigned count; uint32_t tx_enable; /* R300_TX_ENABLE: 0x4101 */ - struct r300_texture_sampler_state { - struct r300_texture_format_state format; - uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ - uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */ - uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ - } regs[16]; + struct r300_texture_sampler_state regs[16]; }; struct r300_vertex_stream_state { @@ -228,10 +239,6 @@ struct r300_constant_buffer { struct r300_query { /* The kind of query. Currently only OQ is supported. */ unsigned type; - /* Whether this query is currently active. Only active queries will - * get emitted into the command stream, and only active queries get - * tallied. */ - boolean active; /* The current count of this query. Required to be at least 32 bits. */ unsigned int count; /* The offset of this query into the query buffer, in bytes. */ @@ -297,16 +304,6 @@ struct r300_texture { enum r300_buffer_tiling microtile, macrotile; }; -struct r300_vertex_info { - /* Parent class */ - struct vertex_info vinfo; - - /* R300_VAP_PROG_STREAK_CNTL_[0-7] */ - uint32_t vap_prog_stream_cntl[8]; - /* R300_VAP_PROG_STREAK_CNTL_EXT_[0-7] */ - uint32_t vap_prog_stream_cntl_ext[8]; -}; - struct r300_vertex_element_state { unsigned count; struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; @@ -314,8 +311,6 @@ struct r300_vertex_element_state { struct r300_vertex_stream_state vertex_stream; }; -extern struct pipe_viewport_state r300_viewport_identity; - struct r300_context { /* Parent class */ struct pipe_context context; @@ -331,8 +326,7 @@ struct r300_context { void (*emit_draw_elements)( struct r300_context *r300, struct pipe_resource* indexBuffer, - unsigned indexSize, int indexBias, - unsigned minIndex, unsigned maxIndex, + unsigned indexSize, unsigned minIndex, unsigned maxIndex, unsigned mode, unsigned start, unsigned count); @@ -436,6 +430,8 @@ struct r300_context { boolean stencil_ref_bf_fallback; /* Point sprites texcoord index, 1 bit per texcoord */ int sprite_coord_enable; + /* Whether two-sided color selection is enabled (AKA light_twoside). */ + boolean two_sided_color; /* upload managers */ struct u_upload_mgr *upload_vb; diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index 8eb321fa08a..85a1aa7b06e 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -40,6 +40,7 @@ static struct debug_option debug_options[] = { { "texalloc", DBG_TEXALLOC, "Texture allocation (for debugging)" }, { "fall", DBG_FALL, "Fallbacks (for debugging)" }, { "rs", DBG_RS, "Rasterizer (for debugging)" }, + { "fb", DBG_FB, "Framebuffer (for debugging)" }, { "anisohq", DBG_ANISOHQ, "High quality anisotropic filtering (for benchmarking)" }, { "notiling", DBG_NO_TILING, "Disable tiling (for benchmarking)" }, { "noimmd", DBG_NO_IMMD, "Disable immediate mode (for benchmarking)" }, @@ -97,3 +98,84 @@ void r300_init_debug(struct r300_screen * screen) } } } + +void r500_dump_rs_block(struct r300_rs_block *rs) +{ + unsigned count, ip, it_count, ic_count, i, j; + unsigned tex_ptr; + unsigned col_ptr, col_fmt; + + count = rs->inst_count & 0xf; + count++; + + it_count = rs->count & 0x7f; + ic_count = (rs->count >> 7) & 0xf; + + fprintf(stderr, "RS Block: %d texcoords (linear), %d colors (perspective)\n", + it_count, ic_count); + fprintf(stderr, "%d instructions\n", count); + + for (i = 0; i < count; i++) { + if (rs->inst[i] & 0x10) { + ip = rs->inst[i] & 0xf; + fprintf(stderr, "texture: ip %d to psf %d\n", + ip, (rs->inst[i] >> 5) & 0x7f); + + tex_ptr = rs->ip[ip] & 0xffffff; + fprintf(stderr, " : "); + + j = 3; + do { + if (tex_ptr & 0x3f == 63) { + fprintf(stderr, "1.0"); + } else if (tex_ptr & 0x3f == 62) { + fprintf(stderr, "0.0"); + } else { + fprintf(stderr, "[%d]", tex_ptr & 0x3f); + } + } while (j-- && fprintf(stderr, "/")); + fprintf(stderr, "\n"); + } + + if (rs->inst[i] & 0x10000) { + ip = (rs->inst[i] >> 12) & 0xf; + fprintf(stderr, "color: ip %d to psf %d\n", + ip, (rs->inst[i] >> 18) & 0x7f); + + col_ptr = (rs->ip[ip] >> 24) & 0x7; + col_fmt = (rs->ip[ip] >> 27) & 0xf; + fprintf(stderr, " : offset %d ", col_ptr); + + switch (col_fmt) { + case 0: + fprintf(stderr, "(R/G/B/A)"); + break; + case 1: + fprintf(stderr, "(R/G/B/0)"); + break; + case 2: + fprintf(stderr, "(R/G/B/1)"); + break; + case 4: + fprintf(stderr, "(0/0/0/A)"); + break; + case 5: + fprintf(stderr, "(0/0/0/0)"); + break; + case 6: + fprintf(stderr, "(0/0/0/1)"); + break; + case 8: + fprintf(stderr, "(1/1/1/A)"); + break; + case 9: + fprintf(stderr, "(1/1/1/0)"); + break; + case 10: + fprintf(stderr, "(1/1/1/1)"); + break; + } + fprintf(stderr, "\n"); + } + } +} diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 23bbc6a99c8..7f7f2929cc3 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -525,8 +525,6 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) OUT_CS(((fb->width + 1440-1) << R300_SCISSORS_X_SHIFT) | ((fb->height + 1440-1) << R300_SCISSORS_Y_SHIFT)); } - OUT_CS_REG(R300_GA_POINT_MINMAX, - (MAX2(fb->width, fb->height) * 6) << R300_GA_POINT_MINMAX_MAX_SHIFT); END_CS; } @@ -550,8 +548,8 @@ void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state) } -static void r300_emit_query_finish(struct r300_context *r300, - struct r300_query *query) +static void r300_emit_query_end_frag_pipes(struct r300_context *r300, + struct r300_query *query) { struct r300_capabilities* caps = &r300->screen->caps; CS_LOCALS(r300); @@ -606,8 +604,8 @@ static void r300_emit_query_finish(struct r300_context *r300, END_CS; } -static void rv530_emit_query_single(struct r300_context *r300, - struct r300_query *query) +static void rv530_emit_query_end_single_z(struct r300_context *r300, + struct r300_query *query) { CS_LOCALS(r300); @@ -619,8 +617,8 @@ static void rv530_emit_query_single(struct r300_context *r300, END_CS; } -static void rv530_emit_query_double(struct r300_context *r300, - struct r300_query *query) +static void rv530_emit_query_end_double_z(struct r300_context *r300, + struct r300_query *query) { CS_LOCALS(r300); @@ -648,11 +646,13 @@ void r300_emit_query_end(struct r300_context* r300) if (caps->family == CHIP_FAMILY_RV530) { if (caps->num_z_pipes == 2) - rv530_emit_query_double(r300, query); + rv530_emit_query_end_double_z(r300, query); else - rv530_emit_query_single(r300, query); + rv530_emit_query_end_single_z(r300, query); } else - r300_emit_query_finish(r300, query); + r300_emit_query_end_frag_pipes(r300, query); + + query->begin_emitted = FALSE; } void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state) @@ -667,7 +667,9 @@ void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_GB_AA_CONFIG, rs->antialiasing_config); OUT_CS_REG(R300_GA_POINT_SIZE, rs->point_size); - OUT_CS_REG(R300_GA_LINE_CNTL, rs->line_control); + OUT_CS_REG_SEQ(R300_GA_POINT_MINMAX, 2); + OUT_CS(rs->point_minmax); + OUT_CS(rs->line_control); if (rs->polygon_offset_enable) { scale = rs->depth_scale * 12; @@ -714,6 +716,10 @@ void r300_emit_rs_block_state(struct r300_context* r300, unsigned count = (rs->inst_count & R300_RS_INST_COUNT_MASK) + 1; CS_LOCALS(r300); + if (SCREEN_DBG_ON(r300->screen, DBG_DRAW)) { + r500_dump_rs_block(rs); + } + DBG(r300, DBG_DRAW, "r300: RS emit:\n"); BEGIN_CS(size); @@ -1003,16 +1009,16 @@ void r300_emit_viewport_state(struct r300_context* r300, struct r300_viewport_state* viewport = (struct r300_viewport_state*)state; CS_LOCALS(r300); - BEGIN_CS(size); - OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); - OUT_CS_32F(viewport->xscale); - OUT_CS_32F(viewport->xoffset); - OUT_CS_32F(viewport->yscale); - OUT_CS_32F(viewport->yoffset); - OUT_CS_32F(viewport->zscale); - OUT_CS_32F(viewport->zoffset); - OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); - END_CS; + BEGIN_CS(size); + OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); + OUT_CS_32F(viewport->xscale); + OUT_CS_32F(viewport->xoffset); + OUT_CS_32F(viewport->yscale); + OUT_CS_32F(viewport->yoffset); + OUT_CS_32F(viewport->zscale); + OUT_CS_32F(viewport->zoffset); + OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); + END_CS; } void r300_emit_ztop_state(struct r300_context* r300, @@ -1094,7 +1100,8 @@ validate: } } /* ...occlusion query buffer... */ - if (r300->query_start.dirty) { + if (r300->query_start.dirty || + (r300->query_current && r300->query_current->begin_emitted)) { if (!r300_add_buffer(r300->rws, r300->oqbo, 0, RADEON_GEM_DOMAIN_GTT)) { r300->context.flush(&r300->context, 0, NULL); @@ -1152,8 +1159,6 @@ unsigned r300_get_num_dirty_dwords(struct r300_context *r300) } } - /* emit_query_end is not atomized. */ - dwords += 26; /* let's reserve some more, just in case */ dwords += 32; diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index e78c6a3624f..d6876c1903f 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2010 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -37,6 +38,8 @@ static void r300_flush(struct pipe_context* pipe, struct r300_context *r300 = r300_context(pipe); struct r300_query *query; struct r300_atom *atom; + struct pipe_framebuffer_state *fb; + unsigned i; CS_LOCALS(r300); (void) cs_count; @@ -48,15 +51,15 @@ static void r300_flush(struct pipe_context* pipe, draw_flush(r300->draw); } - r300_emit_query_end(r300); - if (r300->dirty_hw) { + r300_emit_query_end(r300); + FLUSH_CS; r300->dirty_hw = 0; /* New kitchen sink, baby. */ foreach(atom, &r300->atom_list) { - if (atom->state) { + if (atom->state || atom->allow_null_state) { atom->dirty = TRUE; } } @@ -72,6 +75,39 @@ static void r300_flush(struct pipe_context* pipe, foreach(query, &r300->query_list) { query->flushed = TRUE; } + + /* XXX + * + * This is a preliminary implementation of glFinish. Note that st/mesa + * uses a non-null fence when glFinish is called and then waits for + * the fence. Instead of returning the actual fence, we do the sync + * directly. + * + * The ideal implementation should use something like EmitIrqLocked and + * WaitIrq, or better, real fences. + * + * This feature degrades performance to the level of r300c for games that + * use glFinish a lot, even openarena does. Ideally we wouldn't need + * glFinish at all if we had proper throttling in swapbuffers so that + * the CPU wouldn't outrun the GPU by several frames, so this is basically + * a temporary fix for the input lag. Once swap&sync works with DRI2, + * I'll be happy to remove this code. + * + * - M. */ + if (fence && r300->fb_state.state) { + fb = r300->fb_state.state; + + for (i = 0; i < fb->nr_cbufs; i++) { + if (fb->cbufs[i]->texture) { + r300->rws->buffer_wait(r300->rws, + r300_texture(fb->cbufs[i]->texture)->buffer); + } + if (fb->zsbuf) { + r300->rws->buffer_wait(r300->rws, + r300_texture(fb->zsbuf->texture)->buffer); + } + } + } } void r300_init_flush_functions(struct r300_context* r300) diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 88303f074cd..30aa0651399 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -137,6 +137,7 @@ static void get_external_state( { struct r300_textures_state *texstate = r300->textures_state.state; unsigned i; + unsigned char *swizzle; for (i = 0; i < texstate->sampler_state_count; i++) { struct r300_sampler_state* s = texstate->sampler_states[i]; @@ -146,9 +147,18 @@ static void get_external_state( } if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { - /* XXX Gallium doesn't provide us with any information regarding - * this mode, so we are screwed. I'm setting 0 = LUMINANCE. */ - state->unit[i].depth_texture_mode = 0; + state->unit[i].compare_mode_enabled = 1; + + /* Pass depth texture swizzling to the compiler. */ + if (texstate->sampler_views[i]) { + swizzle = texstate->sampler_views[i]->swizzle; + + state->unit[i].depth_texture_swizzle = + RC_MAKE_SWIZZLE(swizzle[0], swizzle[1], + swizzle[2], swizzle[3]); + } else { + state->unit[i].depth_texture_swizzle = RC_SWIZZLE_XYZW; + } /* Fortunately, no need to translate this. */ state->unit[i].texture_compare_func = s->state.compare_func; diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 5c27796e894..6acbac22196 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -43,8 +43,6 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, q->type = query_type; assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); - q->active = FALSE; - if (r300screen->caps.family == CHIP_FAMILY_RV530) query_size = r300screen->caps.num_z_pipes * sizeof(uint32_t); else @@ -59,6 +57,7 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, /* XXX */ if (q->offset >= 4096) { q->offset = 0; + fprintf(stderr, "r300: Rewinding OQBO...\n"); } return (struct pipe_query*)q; @@ -80,7 +79,12 @@ static void r300_begin_query(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_query* q = (struct r300_query*)query; - assert(r300->query_current == NULL); + if (r300->query_current != NULL) { + fprintf(stderr, "r300: begin_query: " + "Some other query has already been started.\n"); + assert(0); + return; + } pipe_buffer_write(pipe, r300->oqbo, @@ -97,10 +101,14 @@ static void r300_end_query(struct pipe_context* pipe, struct pipe_query* query) { struct r300_context* r300 = r300_context(pipe); - struct r300_query* q = (struct r300_query*)query; + + if ((struct r300_query*)query != r300->query_current) { + fprintf(stderr, "r300: end_query: Got invalid query.\n"); + assert(0); + return; + } r300_emit_query_end(r300); - q->begin_emitted = false; r300->query_current = NULL; } diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 7c3a7902a49..e1f61982be2 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -114,16 +114,79 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, return color_control; } +static void r500_emit_index_offset(struct r300_context *r300, int index_bias) +{ + CS_LOCALS(r300); + + if (r300->screen->caps.is_r500 && + r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0)) { + BEGIN_CS(2); + OUT_CS_REG(R500_VAP_INDEX_OFFSET, + (index_bias & 0xFFFFFF) | (index_bias < 0 ? 1<<24 : 0)); + END_CS; + } else { + if (index_bias) { + fprintf(stderr, "r300: Non-zero index bias is unsupported " + "on this hardware.\n"); + assert(0); + } + } +} + +enum r300_prepare_flags { + PREP_FIRST_DRAW = (1 << 0), + PREP_VALIDATE_VBOS = (1 << 1), + PREP_EMIT_AOS = (1 << 2), + PREP_INDEXED = (1 << 3) +}; + /* Check if the requested number of dwords is available in the CS and - * if not, flush. Return TRUE if the flush occured. */ -static boolean r300_reserve_cs_space(struct r300_context *r300, - unsigned dwords) + * if not, flush. Then validate buffers and emit dirty state. + * Return TRUE if flush occured. */ +static void r300_prepare_for_rendering(struct r300_context *r300, + enum r300_prepare_flags flags, + struct pipe_resource *index_buffer, + unsigned cs_dwords, + unsigned aos_offset, + int index_bias) { - if (!r300->rws->check_cs(r300->rws, dwords)) { + boolean flushed = FALSE; + boolean first_draw = flags & PREP_FIRST_DRAW; + boolean emit_aos = flags & PREP_EMIT_AOS; + + /* Stencil ref fallback. */ + if (r300->stencil_ref_bf_fallback) { + cs_dwords = cs_dwords * 2 + 10; + } + + /* Add dirty state, index offset, and AOS. */ + if (first_draw) { + cs_dwords += r300_get_num_dirty_dwords(r300); + + if (r300->screen->caps.is_r500) + cs_dwords += 2; /* emit_index_offset */ + + if (emit_aos) + cs_dwords += 55; /* emit_aos */ + } + + /* Emitted in flush. */ + cs_dwords += 26; /* emit_query_end */ + + /* Reserve requested CS space. */ + if (!r300->rws->check_cs(r300->rws, cs_dwords)) { r300->context.flush(&r300->context, 0, NULL); - return TRUE; + flushed = TRUE; + } + + /* Validate buffers and emit dirty state if needed. */ + if (first_draw || flushed) { + r300_emit_buffer_validate(r300, flags & PREP_VALIDATE_VBOS, index_buffer); + r300_emit_dirty_state(r300); + r500_emit_index_offset(r300, index_bias); + if (emit_aos) + r300_emit_aos(r300, aos_offset, flags & PREP_INDEXED); } - return FALSE; } static boolean immd_is_good_idea(struct r300_context *r300, @@ -135,7 +198,15 @@ static boolean immd_is_good_idea(struct r300_context *r300, unsigned vertex_element_count = r300->velems->count; unsigned i, vbi; - if (count > 10 || DBG_ON(r300, DBG_NO_IMMD)) { + if (DBG_ON(r300, DBG_NO_IMMD)) { + return FALSE; + } + + if (r300->draw) { + return FALSE; + } + + if (count > 10) { return FALSE; } @@ -166,24 +237,6 @@ static boolean immd_is_good_idea(struct r300_context *r300, * after resolving fallback issues (e.g. stencil ref two-sided). * ****************************************************************************/ -static boolean r500_emit_index_offset(struct r300_context *r300, int indexBias) -{ - CS_LOCALS(r300); - - if (r300->screen->caps.is_r500 && - r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0)) { - BEGIN_CS(2); - OUT_CS_REG(R500_VAP_INDEX_OFFSET, - (indexBias & 0xFFFFFF) | (indexBias < 0 ? 1<<24 : 0)); - END_CS; - } else { - if (indexBias) - return FALSE; /* Can't do anything :( */ - } - - return TRUE; -} - void r500_emit_draw_arrays_immediate(struct r300_context *r300, unsigned mode, unsigned start, @@ -235,11 +288,7 @@ void r500_emit_draw_arrays_immediate(struct r300_context *r300, dwords = 9 + count * vertex_size; - r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2 + dwords); - r300_emit_buffer_validate(r300, FALSE, NULL); - r300_emit_dirty_state(r300); - - r500_emit_index_offset(r300, 0); + r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0); BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, @@ -291,8 +340,6 @@ void r500_emit_draw_arrays(struct r300_context *r300, return; } - r500_emit_index_offset(r300, 0); - BEGIN_CS(7 + (alt_num_verts ? 2 : 0)); if (alt_num_verts) { OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); @@ -312,7 +359,6 @@ void r500_emit_draw_arrays(struct r300_context *r300, void r500_emit_draw_elements(struct r300_context *r300, struct pipe_resource* indexBuffer, unsigned indexSize, - int indexBias, unsigned minIndex, unsigned maxIndex, unsigned mode, @@ -335,12 +381,6 @@ void r500_emit_draw_elements(struct r300_context *r300, DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", count, minIndex, maxIndex); - if (!r500_emit_index_offset(r300, indexBias)) { - fprintf(stderr, "r300: Got a non-zero index bias, " - "refusing to render.\n"); - return; - } - BEGIN_CS(13 + (alt_num_verts ? 2 : 0)); if (alt_num_verts) { OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); @@ -457,7 +497,6 @@ void r300_emit_draw_arrays(struct r300_context *r300, void r300_emit_draw_elements(struct r300_context *r300, struct pipe_resource* indexBuffer, unsigned indexSize, - int indexBias, unsigned minIndex, unsigned maxIndex, unsigned mode, @@ -465,14 +504,14 @@ void r300_emit_draw_elements(struct r300_context *r300, unsigned count) { if (!r300->stencil_ref_bf_fallback) { - r500_emit_draw_elements(r300, indexBuffer, indexSize, indexBias, + r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count); } else { r300_begin_stencil_ref_fallback(r300); - r500_emit_draw_elements(r300, indexBuffer, indexSize, indexBias, + r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count); r300_switch_stencil_ref_side(r300); - r500_emit_draw_elements(r300, indexBuffer, indexSize, indexBias, + r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count); r300_end_stencil_ref_fallback(r300); } @@ -576,36 +615,33 @@ 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, TRUE); + /* 15 dwords for emit_draw_elements */ + r300_prepare_for_rendering(r300, + PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED, + indexBuffer, 15, 0, indexBias); 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, indexBias, + r300->emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count); } else { do { short_count = MIN2(count, 65534); - r300->emit_draw_elements(r300, indexBuffer, indexSize, indexBias, + r300->emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, short_count); start += short_count; count -= short_count; - /* 16 spare dwords are enough for emit_draw_elements. - * Also reserve some space for emit_query_end. */ - if (count && r300_reserve_cs_space(r300, 74)) { - r300_emit_buffer_validate(r300, TRUE, indexBuffer); - r300_emit_dirty_state(r300); - r300_emit_aos(r300, 0, TRUE); + /* 15 dwords for emit_draw_elements */ + if (count) { + r300_prepare_for_rendering(r300, + PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED, + indexBuffer, 15, 0, indexBias); } } while (count); } @@ -650,30 +686,25 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, if (immd_is_good_idea(r300, count)) { r300->emit_draw_arrays_immediate(r300, mode, start, count); } else { - /* Make sure there are at least 128 spare dwords in the command buffer. - * (most of it being consumed by emit_aos) */ - r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); - r300_emit_buffer_validate(r300, TRUE, NULL); - r300_emit_dirty_state(r300); + /* 9 spare dwords for emit_draw_arrays. */ + r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS, + NULL, 9, start, 0); if (alt_num_verts || count <= 65535) { - r300_emit_aos(r300, start, FALSE); r300->emit_draw_arrays(r300, mode, count); } else { do { short_count = MIN2(count, 65535); - r300_emit_aos(r300, start, FALSE); r300->emit_draw_arrays(r300, mode, short_count); start += short_count; count -= short_count; - /* Again, we emit both AOS and draw_arrays so there should be - * at least 128 spare dwords. - * Also reserve some space for emit_query_end. */ - if (count && r300_reserve_cs_space(r300, 186)) { - r300_emit_buffer_validate(r300, TRUE, NULL); - r300_emit_dirty_state(r300); + /* 9 spare dwords for emit_draw_arrays. */ + if (count) { + r300_prepare_for_rendering(r300, + PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, + start, 0); } } while (count); } @@ -704,6 +735,8 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, return; } + r300_update_derived_state(r300); + for (i = 0; i < r300->vertex_buffer_count; i++) { void* buf = pipe_buffer_map(pipe, r300->vertex_buffer[i].buffer, @@ -716,6 +749,10 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, draw_arrays(r300->draw, mode, start, count); + /* XXX Not sure whether this is the best fix. + * It prevents CS from being rejected and weird assertion failures. */ + draw_flush(r300->draw); + for (i = 0; i < r300->vertex_buffer_count; i++) { pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, vb_transfer[i]); @@ -748,6 +785,8 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, return; } + r300_update_derived_state(r300); + for (i = 0; i < r300->vertex_buffer_count; i++) { void* buf = pipe_buffer_map(pipe, r300->vertex_buffer[i].buffer, @@ -763,6 +802,10 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, draw_arrays(r300->draw, mode, start, count); + /* XXX Not sure whether this is the best fix. + * It prevents CS from being rejected and weird assertion failures. */ + draw_flush(r300->draw); + for (i = 0; i < r300->vertex_buffer_count; i++) { pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, vb_transfer[i]); @@ -796,7 +839,7 @@ struct r300_render { size_t vbo_max_used; void * vbo_ptr; - struct pipe_transfer *vbo_transfer; + struct pipe_transfer *vbo_transfer; }; static INLINE struct r300_render* @@ -811,8 +854,6 @@ r300_render_get_vertex_info(struct vbuf_render* render) struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; - r300_update_derived_state(r300); - return &r300->vertex_info; } @@ -860,10 +901,6 @@ static void r300_render_unmap_vertices(struct vbuf_render* render, { struct r300_render* r300render = r300_render(render); struct pipe_context* context = &r300render->r300->context; - CS_LOCALS(r300render->r300); - BEGIN_CS(2); - OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max); - END_CS; r300render->vbo_max_used = MAX2(r300render->vbo_max_used, r300render->vertex_size * (max + 1)); @@ -895,42 +932,64 @@ static void r500_render_draw_arrays(struct vbuf_render* render, { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; + uint8_t* ptr; + unsigned i; + unsigned dwords = 6; CS_LOCALS(r300); - r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2); - r300_emit_buffer_validate(r300, FALSE, NULL); - r300_emit_dirty_state(r300); + (void) i; (void) ptr; + + r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0); DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count); - r500_emit_index_offset(r300, 0); + /* Uncomment to dump all VBOs rendered through this interface. + * Slow and noisy! + ptr = pipe_buffer_map(&r300render->r300->context, + r300render->vbo, PIPE_TRANSFER_READ, + &r300render->vbo_transfer); - BEGIN_CS(2); + for (i = 0; i < count; i++) { + printf("r300: Vertex %d\n", i); + draw_dump_emitted_vertex(&r300->vertex_info, ptr); + ptr += r300->vertex_info.size * 4; + printf("\n"); + } + + pipe_buffer_unmap(&r300render->r300->context, r300render->vbo, + r300render->vbo_transfer); + */ + + BEGIN_CS(dwords); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, r300render->prim)); + OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300render->hwprim); END_CS; } -static void r500_render_draw(struct vbuf_render* render, - const ushort* indices, - uint count) +static void r500_render_draw_elements(struct vbuf_render* render, + const ushort* indices, + uint count) { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; int i; - unsigned dwords = 2 + (count+1)/2; + unsigned dwords = 6 + (count+1)/2; + unsigned max_index = (r300render->vbo_size - r300render->vbo_offset) / + (r300render->r300->vertex_info.size * 4) - 1; CS_LOCALS(r300); - r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); - r300_emit_buffer_validate(r300, FALSE, NULL); - r300_emit_dirty_state(r300); - - r500_emit_index_offset(r300, 0); + r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0); BEGIN_CS(dwords); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, r300render->prim)); + OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | r300render->hwprim); @@ -960,19 +1019,19 @@ static void r300_render_draw_arrays(struct vbuf_render* render, } } -static void r300_render_draw(struct vbuf_render* render, - const ushort* indices, - uint count) +static void r300_render_draw_elements(struct vbuf_render* render, + const ushort* indices, + uint count) { struct r300_context* r300 = r300_render(render)->r300; if (!r300->stencil_ref_bf_fallback) { - r500_render_draw(render, indices, count); + r500_render_draw_elements(render, indices, count); } else { r300_begin_stencil_ref_fallback(r300); - r500_render_draw(render, indices, count); + r500_render_draw_elements(render, indices, count); r300_switch_stencil_ref_side(r300); - r500_render_draw(render, indices, count); + r500_render_draw_elements(render, indices, count); r300_end_stencil_ref_fallback(r300); } } @@ -998,10 +1057,10 @@ static struct vbuf_render* r300_render_create(struct r300_context* r300) r300render->base.unmap_vertices = r300_render_unmap_vertices; r300render->base.set_primitive = r300_render_set_primitive; if (r300->screen->caps.is_r500) { - r300render->base.draw = r500_render_draw; + r300render->base.draw_elements = r500_render_draw_elements; r300render->base.draw_arrays = r500_render_draw_arrays; } else { - r300render->base.draw = r300_render_draw; + r300render->base.draw_elements = r300_render_draw_elements; r300render->base.draw_arrays = r300_render_draw_arrays; } r300render->base.release_vertices = r300_render_release_vertices; diff --git a/src/gallium/drivers/r300/r300_render.h b/src/gallium/drivers/r300/r300_render.h index 4e78914c1ba..71dea218be6 100644 --- a/src/gallium/drivers/r300/r300_render.h +++ b/src/gallium/drivers/r300/r300_render.h @@ -35,7 +35,6 @@ void r500_emit_draw_arrays(struct r300_context *r300, void r500_emit_draw_elements(struct r300_context *r300, struct pipe_resource* indexBuffer, unsigned indexSize, - int indexBias, unsigned minIndex, unsigned maxIndex, unsigned mode, @@ -54,7 +53,6 @@ void r300_emit_draw_arrays(struct r300_context *r300, void r300_emit_draw_elements(struct r300_context *r300, struct pipe_resource* indexBuffer, unsigned indexSize, - int indexBias, unsigned minIndex, unsigned maxIndex, unsigned mode, diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index b7f1c617f03..ef0255066b7 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -76,20 +76,19 @@ static const char* r300_get_name(struct pipe_screen* pscreen) return chip_families[r300screen->caps.family]; } -static int r300_get_param(struct pipe_screen* pscreen, int param) +static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) { struct r300_screen* r300screen = r300_screen(pscreen); + boolean is_r400 = r300screen->caps.is_r400; + boolean is_r500 = r300screen->caps.is_r500; + + /* XXX extended shader capabilities of r400 unimplemented */ + is_r400 = FALSE; switch (param) { - case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: - case PIPE_CAP_MAX_COMBINED_SAMPLERS: - return r300screen->caps.num_tex_units; + /* Supported features (boolean caps). */ case PIPE_CAP_NPOT_TEXTURES: - /* XXX enable now to get GL2.1 API, - * figure out later how to emulate this */ - return 1; case PIPE_CAP_TWO_SIDED_STENCIL: - return 1; case PIPE_CAP_GLSL: /* I'll be frank. This is a lie. * @@ -106,59 +105,103 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) * * ~ C. */ - return 1; - case PIPE_CAP_DUAL_SOURCE_BLEND: - return 0; case PIPE_CAP_ANISOTROPIC_FILTER: - return 1; case PIPE_CAP_POINT_SPRITE: - return 1; - case PIPE_CAP_MAX_RENDER_TARGETS: - return 4; case PIPE_CAP_OCCLUSION_QUERY: - return 1; case PIPE_CAP_TEXTURE_SHADOW_MAP: - return 1; - case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - if (r300screen->caps.is_r500) { - /* 13 == 4096 */ - return 13; - } else { - /* 12 == 2048 */ - return 12; - } case PIPE_CAP_TEXTURE_MIRROR_CLAMP: - return 1; case PIPE_CAP_TEXTURE_MIRROR_REPEAT: + case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; - case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: - return 0; + + /* Unsupported features (boolean caps). */ + case PIPE_CAP_TIMER_QUERY: + case PIPE_CAP_DUAL_SOURCE_BLEND: case PIPE_CAP_TGSI_CONT_SUPPORTED: + case PIPE_CAP_INDEP_BLEND_ENABLE: + case PIPE_CAP_INDEP_BLEND_FUNC: return 0; - case PIPE_CAP_BLEND_EQUATION_SEPARATE: - return 1; + + /* Texturing. */ + case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: + case PIPE_CAP_MAX_COMBINED_SAMPLERS: + return r300screen->caps.num_tex_units; + case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: + return 0; + case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: + case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: + case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: + /* 13 == 4096, 12 == 2048 */ + return is_r500 ? 13 : 12; + + /* Render targets. */ + case PIPE_CAP_MAX_RENDER_TARGETS: + return 4; + + /* General shader limits and features. */ case PIPE_CAP_SM3: - if (r300screen->caps.is_r500) { - return 1; - } else { - return 0; - } + return is_r500 ? 1 : 0; case PIPE_CAP_MAX_CONST_BUFFERS: return 1; case PIPE_CAP_MAX_CONST_BUFFER_SIZE: return 256; - case PIPE_CAP_INDEP_BLEND_ENABLE: - return 0; - case PIPE_CAP_INDEP_BLEND_FUNC: - return 0; + + /* Fragment coordinate conventions. */ case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return 1; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 0; + + /* Fragment shader limits. */ + case PIPE_CAP_MAX_FS_INSTRUCTIONS: + return is_r500 || is_r400 ? 512 : 96; + case PIPE_CAP_MAX_FS_ALU_INSTRUCTIONS: + return is_r500 || is_r400 ? 512 : 64; + case PIPE_CAP_MAX_FS_TEX_INSTRUCTIONS: + return is_r500 || is_r400 ? 512 : 32; + case PIPE_CAP_MAX_FS_TEX_INDIRECTIONS: + return is_r500 ? 511 : 4; + case PIPE_CAP_MAX_FS_CONTROL_FLOW_DEPTH: + return is_r500 ? 64 : 0; /* Actually unlimited on r500. */ + case PIPE_CAP_MAX_FS_INPUTS: + /* 2 colors + 8 texcoords are always supported + * (minus fog and wpos). + * + * R500 has the ability to turn 3rd and 4th color into + * additional texcoords but there is no two-sided color + * selection then. However the facing bit can be used instead. */ + return 10; + case PIPE_CAP_MAX_FS_CONSTS: + return is_r500 ? 256 : 32; + case PIPE_CAP_MAX_FS_TEMPS: + return is_r500 ? 128 : is_r400 ? 64 : 32; + case PIPE_CAP_MAX_FS_ADDRS: + return 0; + case PIPE_CAP_MAX_FS_PREDS: + return is_r500 ? 1 : 0; + + /* Vertex shader limits. */ + case PIPE_CAP_MAX_VS_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_ALU_INSTRUCTIONS: + return is_r500 ? 1024 : 256; + case PIPE_CAP_MAX_VS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_TEX_INDIRECTIONS: + return 0; + case PIPE_CAP_MAX_VS_CONTROL_FLOW_DEPTH: + return is_r500 ? 4 : 0; /* For loops; not sure about conditionals. */ + case PIPE_CAP_MAX_VS_INPUTS: + return 16; + case PIPE_CAP_MAX_VS_CONSTS: + return 256; + case PIPE_CAP_MAX_VS_TEMPS: + return 32; + case PIPE_CAP_MAX_VS_ADDRS: + return 1; /* XXX guessed */ + case PIPE_CAP_MAX_VS_PREDS: + return is_r500 ? 4 : 0; /* XXX guessed. */ + default: fprintf(stderr, "r300: Implementation error: Bad param %d\n", param); @@ -166,7 +209,7 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) } } -static float r300_get_paramf(struct pipe_screen* pscreen, int param) +static float r300_get_paramf(struct pipe_screen* pscreen, enum pipe_cap param) { struct r300_screen* r300screen = r300_screen(pscreen); diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index d58aa138a70..29492024fe3 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -61,19 +61,23 @@ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) { * those changes. */ /*@{*/ -#define DBG_HELP 0x0000001 -#define DBG_FP 0x0000002 -#define DBG_VP 0x0000004 -#define DBG_CS 0x0000008 -#define DBG_DRAW 0x0000010 -#define DBG_TEX 0x0000020 -#define DBG_FALL 0x0000040 -#define DBG_ANISOHQ 0x0000080 -#define DBG_NO_TILING 0x0000100 -#define DBG_NO_IMMD 0x0000200 -#define DBG_STATS 0x0000400 -#define DBG_RS 0x0000800 -#define DBG_TEXALLOC 0x0001000 +#define DBG_HELP (1 << 0) +/* Logging. */ +#define DBG_FP (1 << 1) +#define DBG_VP (1 << 2) +#define DBG_CS (1 << 3) +#define DBG_DRAW (1 << 4) +#define DBG_TEX (1 << 5) +#define DBG_TEXALLOC (1 << 6) +#define DBG_RS (1 << 7) +#define DBG_FALL (1 << 8) +#define DBG_FB (1 << 9) +/* Features. */ +#define DBG_ANISOHQ (1 << 16) +#define DBG_NO_TILING (1 << 17) +#define DBG_NO_IMMD (1 << 18) +/* Statistics. */ +#define DBG_STATS (1 << 24) /*@}*/ static INLINE boolean SCREEN_DBG_ON(struct r300_screen * screen, unsigned flags) diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 4f41530c16a..67e09362d8e 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -395,13 +395,13 @@ static void r300_set_clip_state(struct pipe_context* pipe, if (r300->screen->caps.has_tcl) { memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state)); r300->clip_state.size = 29; + + r300->clip_state.dirty = TRUE; } else { draw_flush(r300->draw); draw_set_clip_state(r300->draw, state); r300->clip_state.size = 2; } - - r300->clip_state.dirty = TRUE; } static void @@ -573,13 +573,35 @@ static void r300_fb_set_tiling_flags(struct r300_context *r300, } } +static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, + const char *binding) +{ + struct pipe_resource *tex = surf->texture; + struct r300_texture *rtex = r300_texture(tex); + + fprintf(stderr, + "r300: %s[%i] Dim: %ix%i, Offset: %i, ZSlice: %i, " + "Face: %i, Level: %i, Format: %s\n" + + "r300: TEX: Macro: %s, Micro: %s, Pitch: %i, " + "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n", + + binding, index, surf->width, surf->height, surf->offset, + surf->zslice, surf->face, surf->level, + util_format_short_name(surf->format), + + rtex->macrotile ? "YES" : " NO", rtex->microtile ? "YES" : " NO", + rtex->hwpitch[0], tex->width0, tex->height0, tex->depth0, + tex->last_level, util_format_short_name(tex->format)); +} + static void r300_set_framebuffer_state(struct pipe_context* pipe, const struct pipe_framebuffer_state* state) { struct r300_context* r300 = r300_context(pipe); struct pipe_framebuffer_state *old_state = r300->fb_state.state; - unsigned max_width, max_height; + unsigned max_width, max_height, i; uint32_t zbuffer_bpp = 0; if (state->nr_cbufs > 4) { @@ -623,7 +645,7 @@ static void memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) + - (state->zsbuf ? 10 : 0) + 11; + (state->zsbuf ? 10 : 0) + 9; /* Polygon offset depends on the zbuffer bit depth. */ if (state->zsbuf && r300->polygon_offset_enabled) { @@ -641,6 +663,16 @@ static void r300->rs_state.dirty = TRUE; } } + + if (DBG_ON(r300, DBG_FB)) { + fprintf(stderr, "r300: set_framebuffer_state:\n"); + for (i = 0; i < state->nr_cbufs; i++) { + r300_print_fb_surf_info(state->cbufs[i], i, "CB"); + } + if (state->zsbuf) { + r300_print_fb_surf_info(state->zsbuf, 0, "ZB"); + } + } } /* Create fragment shader state. */ @@ -729,9 +761,14 @@ static void* r300_create_rs_state(struct pipe_context* pipe, { struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state); int i; + float psiz; - /* Copy rasterizer state for Draw. */ + /* Copy rasterizer state. */ rs->rs = *state; + rs->rs_draw = *state; + + /* Override some states for Draw. */ + rs->rs_draw.sprite_coord_enable = 0; /* We can do this in HW. */ #ifdef PIPE_ARCH_LITTLE_ENDIAN rs->vap_control_status = R300_VC_NO_SWAP; @@ -744,60 +781,64 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->vap_control_status |= R300_VAP_TCL_BYPASS; } - rs->point_size = pack_float_16_6x(state->point_size) | + /* Point size width and height. */ + rs->point_size = + pack_float_16_6x(state->point_size) | (pack_float_16_6x(state->point_size) << R300_POINTSIZE_X_SHIFT); + /* Point size clamping. */ + if (state->point_size_per_vertex) { + /* Per-vertex point size. + * Clamp to [0, max FB size] */ + psiz = pipe->screen->get_paramf(pipe->screen, + PIPE_CAP_MAX_POINT_WIDTH); + rs->point_minmax = + pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT; + } else { + /* We cannot disable the point-size vertex output, + * so clamp it. */ + psiz = state->point_size; + rs->point_minmax = + (pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MIN_SHIFT) | + (pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT); + } + + /* Line control. */ rs->line_control = pack_float_16_6x(state->line_width) | R300_GA_LINE_CNTL_END_TYPE_COMP; /* Enable polygon mode */ - if (state->fill_cw != PIPE_POLYGON_MODE_FILL || - state->fill_ccw != PIPE_POLYGON_MODE_FILL) { + if (state->fill_front != PIPE_POLYGON_MODE_FILL || + state->fill_back != PIPE_POLYGON_MODE_FILL) { rs->polygon_mode = R300_GA_POLY_MODE_DUAL; } - /* Radeons don't think in "CW/CCW", they think in "front/back". */ - if (state->front_winding == PIPE_WINDING_CW) { - rs->cull_mode = R300_FRONT_FACE_CW; - - /* Polygon offset */ - if (state->offset_cw) { - rs->polygon_offset_enable |= R300_FRONT_ENABLE; - } - if (state->offset_ccw) { - rs->polygon_offset_enable |= R300_BACK_ENABLE; - } - - /* Polygon mode */ - if (rs->polygon_mode) { - rs->polygon_mode |= - r300_translate_polygon_mode_front(state->fill_cw); - rs->polygon_mode |= - r300_translate_polygon_mode_back(state->fill_ccw); - } - } else { + /* Front face */ + if (state->front_ccw) rs->cull_mode = R300_FRONT_FACE_CCW; + else + rs->cull_mode = R300_FRONT_FACE_CW; - /* Polygon offset */ - if (state->offset_ccw) { - rs->polygon_offset_enable |= R300_FRONT_ENABLE; - } - if (state->offset_cw) { - rs->polygon_offset_enable |= R300_BACK_ENABLE; - } + /* Polygon offset */ + if (util_get_offset(state, state->fill_front)) { + rs->polygon_offset_enable |= R300_FRONT_ENABLE; + } + if (util_get_offset(state, state->fill_back)) { + rs->polygon_offset_enable |= R300_BACK_ENABLE; + } - /* Polygon mode */ - if (rs->polygon_mode) { - rs->polygon_mode |= - r300_translate_polygon_mode_front(state->fill_ccw); - rs->polygon_mode |= - r300_translate_polygon_mode_back(state->fill_cw); - } + /* Polygon mode */ + if (rs->polygon_mode) { + rs->polygon_mode |= + r300_translate_polygon_mode_front(state->fill_front); + rs->polygon_mode |= + r300_translate_polygon_mode_back(state->fill_back); } - if (state->front_winding & state->cull_mode) { + + if (state->cull_face & PIPE_FACE_FRONT) { rs->cull_mode |= R300_CULL_FRONT; } - if (~(state->front_winding) & state->cull_mode) { + if (state->cull_face & PIPE_FACE_BACK) { rs->cull_mode |= R300_CULL_BACK; } @@ -856,24 +897,30 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) struct r300_context* r300 = r300_context(pipe); struct r300_rs_state* rs = (struct r300_rs_state*)state; int last_sprite_coord_enable = r300->sprite_coord_enable; + boolean last_two_sided_color = r300->two_sided_color; - if (r300->draw) { + if (r300->draw && rs) { draw_flush(r300->draw); - draw_set_rasterizer_state(r300->draw, &rs->rs, state); + draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state); } if (rs) { - r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; + r300->polygon_offset_enabled = (rs->rs.offset_point || + rs->rs.offset_line || + rs->rs.offset_tri); r300->sprite_coord_enable = rs->rs.sprite_coord_enable; + r300->two_sided_color = rs->rs.light_twoside; } else { r300->polygon_offset_enabled = FALSE; r300->sprite_coord_enable = 0; + r300->two_sided_color = FALSE; } UPDATE_STATE(state, r300->rs_state); - r300->rs_state.size = 26 + (r300->polygon_offset_enabled ? 5 : 0); + r300->rs_state.size = 27 + (r300->polygon_offset_enabled ? 5 : 0); - if (last_sprite_coord_enable != r300->sprite_coord_enable) { + if (last_sprite_coord_enable != r300->sprite_coord_enable || + last_two_sided_color != r300->two_sided_color) { r300->rs_block_state.dirty = TRUE; } } @@ -913,7 +960,7 @@ static void* sampler->min_lod = MAX2((unsigned)state->min_lod, 0); sampler->max_lod = MAX2((unsigned)ceilf(state->max_lod), 0); - lod_bias = CLAMP((int)(state->lod_bias * 32), -(1 << 9), (1 << 9) - 1); + lod_bias = CLAMP((int)(state->lod_bias * 32 + 1), -(1 << 9), (1 << 9) - 1); sampler->filter1 |= lod_bias << R300_LOD_BIAS_SHIFT; @@ -1028,7 +1075,6 @@ r300_create_sampler_view(struct pipe_context *pipe, { struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view); struct r300_texture *tex = r300_texture(texture); - unsigned char swizzle[4]; if (view) { view->base = *templ; @@ -1037,14 +1083,14 @@ r300_create_sampler_view(struct pipe_context *pipe, view->base.texture = NULL; pipe_resource_reference(&view->base.texture, texture); - swizzle[0] = templ->swizzle_r; - swizzle[1] = templ->swizzle_g; - swizzle[2] = templ->swizzle_b; - swizzle[3] = templ->swizzle_a; + view->swizzle[0] = templ->swizzle_r; + view->swizzle[1] = templ->swizzle_g; + view->swizzle[2] = templ->swizzle_b; + view->swizzle[3] = templ->swizzle_a; view->format = tex->tx_format; view->format.format1 |= r300_translate_texformat(templ->format, - swizzle); + view->swizzle); if (r300_screen(pipe->screen)->caps.is_r500) { view->format.format2 |= r500_tx_format_msb_bit(templ->format); } @@ -1081,6 +1127,13 @@ static void r300_set_viewport_state(struct pipe_context* pipe, r300->viewport = *state; + if (r300->draw) { + draw_flush(r300->draw); + draw_set_viewport_state(r300->draw, state); + viewport->vte_control = R300_VTX_XY_FMT | R300_VTX_Z_FMT; + return; + } + /* Do the transform in HW. */ viewport->vte_control = R300_VTX_W0_FMT; @@ -1190,7 +1243,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, } } -/* Update the PSC tables. */ +/* Initialize the PSC tables. */ static void r300_vertex_psc(struct r300_vertex_element_state *velems) { struct r300_vertex_stream_state *vstream = &velems->vertex_stream; @@ -1329,7 +1382,6 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, abort(); } } - } } return velems; @@ -1350,6 +1402,7 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, if (r300->draw) { draw_flush(r300->draw); draw_set_vertex_elements(r300->draw, velems->count, velems->velem); + return; } UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state); @@ -1372,8 +1425,10 @@ static void* r300_create_vs_state(struct pipe_context* pipe, vs->state = *shader; vs->state.tokens = tgsi_dup_tokens(shader->tokens); + r300_init_vs_outputs(vs); + if (r300->screen->caps.has_tcl) { - r300_translate_vertex_shader(r300, vs, vs->state.tokens); + r300_translate_vertex_shader(r300, vs); } else { vs->draw_vs = draw_create_vertex_shader(r300->draw, shader); } @@ -1443,7 +1498,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, struct r300_constant_buffer *cbuf; struct pipe_transfer *tr; void *mapped; - int max_size = 0; + int max_size = 0, max_size_bytes = 0, clamped_size = 0; switch (shader) { case PIPE_SHADER_VERTEX: @@ -1462,6 +1517,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, assert(0); return; } + max_size_bytes = max_size * 4 * sizeof(float); if (buf == NULL || buf->width0 == 0 || (mapped = pipe_buffer_map(pipe, buf, PIPE_TRANSFER_READ, &tr)) == NULL) @@ -1470,19 +1526,21 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, return; } - assert((buf->width0 % 4 * sizeof(float)) == 0); + if (shader == PIPE_SHADER_FRAGMENT || + (shader == PIPE_SHADER_VERTEX && r300->screen->caps.has_tcl)) { + assert((buf->width0 % (4 * sizeof(float))) == 0); - /* Check the size of the constant buffer. */ - /* XXX Subtract immediates and RC_STATE_* variables. */ - if (buf->width0 > (sizeof(float) * 4 * max_size)) { - fprintf(stderr, "r300: Max size of the constant buffer is " - "%i*4 floats.\n", max_size); - abort(); - } + /* Check the size of the constant buffer. */ + /* XXX Subtract immediates and RC_STATE_* variables. */ + if (buf->width0 > max_size_bytes) { + fprintf(stderr, "r300: Max size of the constant buffer is " + "%i*4 floats.\n", max_size); + } + clamped_size = MIN2(buf->width0, max_size_bytes); - memcpy(cbuf->constants, mapped, buf->width0); - cbuf->count = buf->width0 / (4 * sizeof(float)); - pipe_buffer_unmap(pipe, buf, tr); + memcpy(cbuf->constants, mapped, clamped_size); + cbuf->count = clamped_size / (4 * sizeof(float)); + } if (shader == PIPE_SHADER_VERTEX) { if (r300->screen->caps.has_tcl) { @@ -1492,12 +1550,13 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, r300->pvs_flush.dirty = TRUE; } else if (r300->draw) { draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX, - 0, cbuf->constants, - buf->width0); + 0, mapped, buf->width0); } } else if (shader == PIPE_SHADER_FRAGMENT) { r300->fs_constants.dirty = TRUE; } + + pipe_buffer_unmap(pipe, buf, tr); } void r300_init_state_functions(struct r300_context* r300) diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index e3adace0faa..7583862a1a4 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -34,6 +34,7 @@ #include "r300_state.h" #include "r300_state_derived.h" #include "r300_state_inlines.h" +#include "r300_texture.h" #include "r300_vs.h" /* r300_state_derived: Various bits of state which are dependent upon @@ -115,13 +116,12 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300) static void r300_swtcl_vertex_psc(struct r300_context *r300) { struct r300_vertex_stream_state *vstream = r300->vertex_stream_state.state; - struct vertex_info* vinfo = &r300->vertex_info; + struct vertex_info *vinfo = &r300->vertex_info; uint16_t type, swizzle; enum pipe_format format; unsigned i, attrib_count; int* vs_output_tab = r300->stream_loc_notcl; - /* XXX hax */ memset(vstream, 0, sizeof(struct r300_vertex_stream_state)); /* For each Draw attribute, route it to the fragment shader according @@ -354,10 +354,26 @@ static void r300_update_rs_block(struct r300_context *r300) /* Set up back-face colors. The rasterizer will do the color selection * automatically. */ if (any_bcolor_used) { - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR; - rs.vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i); - stream_loc_notcl[loc++] = 4 + i; + if (r300->two_sided_color) { + /* Rasterize as back-face colors. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR; + rs.vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i); + stream_loc_notcl[loc++] = 4 + i; + } + } else { + /* Rasterize two fake texcoords to prevent from the two-sided color + * selection. */ + /* XXX Consider recompiling the vertex shader to save 2 RS units. */ + for (i = 0; i < 2; i++) { + rs.vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << tex_count); + rs.vap_out_vtx_fmt[1] |= (4 << (3 * tex_count)); + stream_loc_notcl[loc++] = 6 + tex_count; + + /* Rasterize it. */ + rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_XYZW); + tex_count++; + } } } @@ -493,6 +509,12 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) unsigned min_level, max_level, i, size; unsigned count = MIN2(state->sampler_view_count, state->sampler_state_count); + unsigned char depth_swizzle[4] = { + UTIL_FORMAT_SWIZZLE_X, + UTIL_FORMAT_SWIZZLE_X, + UTIL_FORMAT_SWIZZLE_X, + UTIL_FORMAT_SWIZZLE_X + }; state->tx_enable = 0; state->count = 0; @@ -512,6 +534,20 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->filter1 = sampler->filter1; texstate->border_color = sampler->border_color; + /* If compare mode is disabled, the sampler view swizzles + * are stored in the format. + * Otherwise, swizzles must be applied after the compare mode + * in the fragment shader. */ + if (util_format_is_depth_or_stencil(tex->b.b.format)) { + if (sampler->state.compare_mode == PIPE_TEX_COMPARE_NONE) { + texstate->format.format1 |= + r300_get_swizzle_combined(depth_swizzle, view->swizzle); + } else { + texstate->format.format1 |= + r300_get_swizzle_combined(depth_swizzle, 0); + } + } + /* to emulate 1D textures through 2D ones correctly */ if (tex->b.b.target == PIPE_TEXTURE_1D) { texstate->filter0 &= ~R300_TX_WRAP_T_MASK; @@ -578,13 +614,13 @@ void r300_update_derived_state(struct r300_context* r300) if (r300->rs_block_state.dirty) { r300_update_rs_block(r300); - } - if (r300->draw) { - memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); - r300_draw_emit_all_attribs(r300); - draw_compute_vertex_size(&r300->vertex_info); - r300_swtcl_vertex_psc(r300); + if (r300->draw) { + memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); + r300_draw_emit_all_attribs(r300); + draw_compute_vertex_size(&r300->vertex_info); + r300_swtcl_vertex_psc(r300); + } } r300_update_hyperz_state(r300); diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index cd9443fa260..34d3a169d57 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -27,11 +27,6 @@ #include "r300_screen.h" #include "r300_state_invariant.h" -struct pipe_viewport_state r300_viewport_identity = { - .scale = {1.0, 1.0, 1.0, 1.0}, - .translate = {0.0, 0.0, 0.0, 0.0}, -}; - /* Calculate and emit invariant state. This is data that the 3D engine * will probably want at the beginning of every CS, but it's not currently * handled by any CSO setup, and in addition it doesn't really change much. diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index d6f629cf9c6..4a5c932b7e8 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -24,6 +24,7 @@ #include "pipe/p_screen.h" #include "util/u_format.h" +#include "util/u_format_s3tc.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -46,6 +47,60 @@ static const unsigned microblock_table[5][3][2] = { {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ }; +unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, + const unsigned char *swizzle_view) +{ + unsigned i; + unsigned char swizzle[4]; + unsigned result = 0; + const uint32_t swizzle_shift[4] = { + R300_TX_FORMAT_R_SHIFT, + R300_TX_FORMAT_G_SHIFT, + R300_TX_FORMAT_B_SHIFT, + R300_TX_FORMAT_A_SHIFT + }; + const uint32_t swizzle_bit[4] = { + R300_TX_FORMAT_X, + R300_TX_FORMAT_Y, + R300_TX_FORMAT_Z, + R300_TX_FORMAT_W + }; + + if (swizzle_view) { + /* Combine two sets of swizzles. */ + for (i = 0; i < 4; i++) { + swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ? + swizzle_format[swizzle_view[i]] : swizzle_view[i]; + } + } else { + memcpy(swizzle, swizzle_format, 4); + } + + /* Get swizzle. */ + for (i = 0; i < 4; i++) { + switch (swizzle[i]) { + case UTIL_FORMAT_SWIZZLE_Y: + result |= swizzle_bit[1] << swizzle_shift[i]; + break; + case UTIL_FORMAT_SWIZZLE_Z: + result |= swizzle_bit[2] << swizzle_shift[i]; + break; + case UTIL_FORMAT_SWIZZLE_W: + result |= swizzle_bit[3] << swizzle_shift[i]; + break; + case UTIL_FORMAT_SWIZZLE_0: + result |= R300_TX_FORMAT_ZERO << swizzle_shift[i]; + break; + case UTIL_FORMAT_SWIZZLE_1: + result |= R300_TX_FORMAT_ONE << swizzle_shift[i]; + break; + default: /* UTIL_FORMAT_SWIZZLE_X */ + result |= swizzle_bit[0] << swizzle_shift[i]; + } + } + return result; +} + /* Translate a pipe_format into a useful texture format for sampling. * * Some special formats are translated directly using R300_EASY_TX_FORMAT, @@ -65,38 +120,26 @@ uint32_t r300_translate_texformat(enum pipe_format format, const struct util_format_description *desc; unsigned i; boolean uniform = TRUE; - const uint32_t swizzle_shift[4] = { - R300_TX_FORMAT_R_SHIFT, - R300_TX_FORMAT_G_SHIFT, - R300_TX_FORMAT_B_SHIFT, - R300_TX_FORMAT_A_SHIFT - }; - const uint32_t swizzle_bit[4] = { - R300_TX_FORMAT_X, - R300_TX_FORMAT_Y, - R300_TX_FORMAT_Z, - R300_TX_FORMAT_W - }; const uint32_t sign_bit[4] = { R300_TX_FORMAT_SIGNED_X, R300_TX_FORMAT_SIGNED_Y, R300_TX_FORMAT_SIGNED_Z, R300_TX_FORMAT_SIGNED_W, }; - unsigned char swizzle[4]; desc = util_format_description(format); /* Colorspace (return non-RGB formats directly). */ switch (desc->colorspace) { - /* Depth stencil formats. */ + /* Depth stencil formats. + * Swizzles are added in r300_merge_textures_and_samplers. */ case UTIL_FORMAT_COLORSPACE_ZS: switch (format) { case PIPE_FORMAT_Z16_UNORM: - return R300_EASY_TX_FORMAT(X, X, X, X, X16); + return R300_TX_FORMAT_X16; case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP); + return R300_TX_FORMAT_W24_FP; default: return ~0; /* Unsupported. */ } @@ -130,46 +173,14 @@ uint32_t r300_translate_texformat(enum pipe_format format, } } - /* Get swizzle. */ - if (swizzle_view) { - /* Compose two sets of swizzles. */ - for (i = 0; i < 4; i++) { - swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ? - desc->swizzle[swizzle_view[i]] : swizzle_view[i]; - } - } else { - memcpy(swizzle, desc->swizzle, sizeof(swizzle)); - } - - /* Add swizzle. */ - for (i = 0; i < 4; i++) { - switch (swizzle[i]) { - case UTIL_FORMAT_SWIZZLE_X: - case UTIL_FORMAT_SWIZZLE_NONE: - result |= swizzle_bit[0] << swizzle_shift[i]; - break; - case UTIL_FORMAT_SWIZZLE_Y: - result |= swizzle_bit[1] << swizzle_shift[i]; - break; - case UTIL_FORMAT_SWIZZLE_Z: - result |= swizzle_bit[2] << swizzle_shift[i]; - break; - case UTIL_FORMAT_SWIZZLE_W: - result |= swizzle_bit[3] << swizzle_shift[i]; - break; - case UTIL_FORMAT_SWIZZLE_0: - result |= R300_TX_FORMAT_ZERO << swizzle_shift[i]; - break; - case UTIL_FORMAT_SWIZZLE_1: - result |= R300_TX_FORMAT_ONE << swizzle_shift[i]; - break; - default: - return ~0; /* Unsupported. */ - } - } + result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view); /* S3TC formats. */ if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { + if (!util_format_s3tc_enabled) { + return ~0; /* Unsupported. */ + } + switch (format) { case PIPE_FORMAT_DXT1_RGB: case PIPE_FORMAT_DXT1_RGBA: @@ -920,6 +931,7 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen, fprintf(stderr, "r300: texture_create: " "Got invalid texture dimensions: %ix%ix%i\n", base->width0, base->height0, base->depth0); + FREE(tex); return NULL; } @@ -948,7 +960,7 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen, util_format_short_name(base->format)); tex->buffer = rws->buffer_create(rws, 2048, - PIPE_BIND_SAMPLER_VIEW, /* XXX */ + base->bind, tex->size); rws->buffer_set_tiling(rws, tex->buffer, tex->pitch[0], diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index ba79ec068a1..2d8f0e14393 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -27,6 +27,9 @@ struct r300_texture; +unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, + const unsigned char *swizzle_view); + uint32_t r300_translate_texformat(enum pipe_format format, const unsigned char *swizzle_view); diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index f0f87c5e2bc..beb321cb238 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -108,6 +108,12 @@ r300_texture_get_transfer(struct pipe_context *ctx, struct r300_transfer *trans; struct pipe_resource base; + /* XXX Why aren't flushes taken care of by winsys automatically? + * Winsys seems to sometimes return a cached buffer instead of + * a mapped hardware buffer if this flush is commented out. */ + if (ctx->is_resource_referenced(ctx, texture, sr.face, sr.level)) + ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); + trans = CALLOC_STRUCT(r300_transfer); if (trans) { /* Initialize the transfer object. */ diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index f3186431e1d..59f89b3482a 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -181,21 +181,23 @@ static void r300_dummy_vertex_shader( state.tokens = ureg_finalize(ureg); shader->dummy = TRUE; - r300_translate_vertex_shader(r300, shader, state.tokens); + r300_translate_vertex_shader(r300, shader); ureg_destroy(ureg); } -void r300_translate_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs, - const struct tgsi_token *tokens) +void r300_init_vs_outputs(struct r300_vertex_shader *vs) +{ + tgsi_scan_shader(vs->state.tokens, &vs->info); + r300_shader_read_vs_outputs(&vs->info, &vs->outputs); +} + +void r300_translate_vertex_shader(struct r300_context *r300, + struct r300_vertex_shader *vs) { struct r300_vertex_program_compiler compiler; struct tgsi_to_rc ttr; - tgsi_scan_shader(tokens, &vs->info); - r300_shader_read_vs_outputs(&vs->info, &vs->outputs); - /* Setup the compiler */ rc_init(&compiler.Base); @@ -205,7 +207,7 @@ void r300_translate_vertex_shader(struct r300_context* r300, if (compiler.Base.Debug) { debug_printf("r300: Initial vertex program\n"); - tgsi_dump(tokens, 0); + tgsi_dump(vs->state.tokens, 0); } /* Translate TGSI to our internal representation */ @@ -213,7 +215,7 @@ void r300_translate_vertex_shader(struct r300_context* r300, ttr.info = &vs->info; ttr.use_half_swizzles = FALSE; - r300_tgsi_to_rc(&ttr, tokens); + r300_tgsi_to_rc(&ttr, vs->state.tokens); compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs + 1)); compiler.SetHwInputOutput = &set_vertex_inputs_outputs; diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index 57b3fbca0bb..31890d78caf 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -56,8 +56,8 @@ struct r300_vertex_shader { void *draw_vs; }; -void r300_translate_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs, - const struct tgsi_token *tokens); +void r300_init_vs_outputs(struct r300_vertex_shader *vs); +void r300_translate_vertex_shader(struct r300_context *r300, + struct r300_vertex_shader *vs); #endif /* R300_VS_H */ diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 1642981eaa8..3d0413f90af 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -87,13 +87,8 @@ struct r300_winsys_screen { 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); + void (*buffer_wait)(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf); /* Add a pipe_resource to the list of buffer objects to validate. */ boolean (*add_buffer)(struct r300_winsys_screen *winsys, diff --git a/src/gallium/drivers/rbug/Makefile b/src/gallium/drivers/rbug/Makefile new file mode 100644 index 00000000000..64e172fe5c1 --- /dev/null +++ b/src/gallium/drivers/rbug/Makefile @@ -0,0 +1,12 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = rbug + +C_SOURCES = \ + rbug_core.c \ + rbug_context.c \ + rbug_objects.c \ + rbug_screen.c + +include ../../Makefile.template diff --git a/src/gallium/drivers/rbug/README b/src/gallium/drivers/rbug/README new file mode 100644 index 00000000000..b6d3a5cf351 --- /dev/null +++ b/src/gallium/drivers/rbug/README @@ -0,0 +1,58 @@ + RBUG PIPE DRIVER + + += About = + +This directory contains a Gallium3D remote debugger pipe driver. +It provides remote debugging functionality. + + += Build Instructions = + +To build, invoke scons on the top dir as + + scons dri=no statetrackers=mesa winsys=xlib + + += Usage = + +To use do + + export LD_LIBRARY_PATH=$PWD/build/linux-x86-debug/lib + +ensure the right libGL.so is being picked by doing + + ldd progs/trivial/tri + + export XMESA_TRACE=y + GALLIUM_RBUG=true progs/trivial/tri + +which should open gallium remote debugging session. While the program is running +you can launch the small remote debugging application from progs/rbug. More +information is in that directory. Also for a gui see: + + http://cgit.freedesktop.org/mesa/rbug-gui + + += Integrating = + +You can integrate the rbug pipe driver either inside the state tracker or the +target. The procedure on both cases is the same. Let's assume you have a +pipe_screen obtained by the usual means (variable and function names are just +for illustration purposes): + + real_screen = real_screen_create(...); + +The rbug screen is then created by doing + + rbug_screen = rbug_screen_create(real_screen); + +You can then simply use rbug_screen instead of real_screen. + +You can create as many contexts you wish from rbug_screen::context_create they +are automatically wrapped by rbug_screen. + + +-- +Jose Fonseca <[email protected]> +Jakob Bornecrantz <[email protected]> diff --git a/src/gallium/drivers/rbug/SConscript b/src/gallium/drivers/rbug/SConscript new file mode 100644 index 00000000000..3da6ac104a4 --- /dev/null +++ b/src/gallium/drivers/rbug/SConscript @@ -0,0 +1,14 @@ +Import('*') + +env = env.Clone() + +rbug = env.ConvenienceLibrary( + target = 'rbug', + source = [ + 'rbug_context.c', + 'rbug_core.c', + 'rbug_objects.c', + 'rbug_screen.c', + ]) + +Export('rbug') diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c new file mode 100644 index 00000000000..59f005ec16c --- /dev/null +++ b/src/gallium/drivers/rbug/rbug_context.c @@ -0,0 +1,1072 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * 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 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 VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "pipe/p_context.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_simple_list.h" + +#include "rbug/rbug_context.h" + +#include "rbug_context.h" +#include "rbug_objects.h" + + +static void +rbug_destroy(struct pipe_context *_pipe) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->destroy(pipe); + + FREE(rb_pipe); +} + +static void +rbug_draw_block_locked(struct rbug_context *rb_pipe, int flag) +{ + + if (rb_pipe->draw_blocker & flag) { + rb_pipe->draw_blocked |= flag; + } else if ((rb_pipe->draw_rule.blocker & flag) && + (rb_pipe->draw_blocker & RBUG_BLOCK_RULE)) { + int k; + boolean block = FALSE; + debug_printf("%s (%p %p) (%p %p) (%p %u) (%p %u)\n", __FUNCTION__, + (void *) rb_pipe->draw_rule.fs, (void *) rb_pipe->curr.fs, + (void *) rb_pipe->draw_rule.vs, (void *) rb_pipe->curr.vs, + (void *) rb_pipe->draw_rule.surf, 0, + (void *) rb_pipe->draw_rule.texture, 0); + if (rb_pipe->draw_rule.fs && + rb_pipe->draw_rule.fs == rb_pipe->curr.fs) + block = TRUE; + if (rb_pipe->draw_rule.vs && + rb_pipe->draw_rule.vs == rb_pipe->curr.vs) + block = TRUE; + if (rb_pipe->draw_rule.surf && + rb_pipe->draw_rule.surf == rb_pipe->curr.zsbuf) + block = TRUE; + if (rb_pipe->draw_rule.surf) + for (k = 0; k < rb_pipe->curr.nr_cbufs; k++) + if (rb_pipe->draw_rule.surf == rb_pipe->curr.cbufs[k]) + block = TRUE; + if (rb_pipe->draw_rule.texture) { + for (k = 0; k < rb_pipe->curr.num_fs_views; k++) + if (rb_pipe->draw_rule.texture == rb_pipe->curr.fs_texs[k]) + block = TRUE; + for (k = 0; k < rb_pipe->curr.num_vs_views; k++) { + if (rb_pipe->draw_rule.texture == rb_pipe->curr.vs_texs[k]) { + block = TRUE; + } + } + } + + if (block) + rb_pipe->draw_blocked |= (flag | RBUG_BLOCK_RULE); + } + + if (rb_pipe->draw_blocked) + rbug_notify_draw_blocked(rb_pipe); + + /* wait for rbug to clear the blocked flag */ + while (rb_pipe->draw_blocked & flag) { + rb_pipe->draw_blocked |= flag; +#ifdef PIPE_THREAD_HAVE_CONDVAR + pipe_condvar_wait(rb_pipe->draw_cond, rb_pipe->draw_mutex); +#else + pipe_mutex_unlock(rb_pipe->draw_mutex); +#ifdef PIPE_SUBSYSTEM_WINDOWS_USER + Sleep(1); +#endif + pipe_mutex_lock(rb_pipe->draw_mutex); +#endif + } + +} + +static void +rbug_draw_arrays(struct pipe_context *_pipe, + unsigned prim, + unsigned start, + unsigned count) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe_mutex_lock(rb_pipe->draw_mutex); + rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_BEFORE); + + pipe->draw_arrays(pipe, + prim, + start, + count); + + rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_AFTER); + pipe_mutex_unlock(rb_pipe->draw_mutex); +} + +static void +rbug_draw_elements(struct pipe_context *_pipe, + struct pipe_resource *_indexResource, + unsigned indexSize, + int indexBias, + unsigned prim, + unsigned start, + unsigned count) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource = rbug_resource(_indexResource); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *indexResource = rb_resource->resource; + + pipe_mutex_lock(rb_pipe->draw_mutex); + rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_BEFORE); + + pipe->draw_elements(pipe, + indexResource, + indexSize, + indexBias, + prim, + start, + count); + + rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_AFTER); + pipe_mutex_unlock(rb_pipe->draw_mutex); +} + +static void +rbug_draw_range_elements(struct pipe_context *_pipe, + struct pipe_resource *_indexResource, + unsigned indexSize, + int indexBias, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource = rbug_resource(_indexResource); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *indexResource = rb_resource->resource; + + pipe_mutex_lock(rb_pipe->draw_mutex); + rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_BEFORE); + + pipe->draw_range_elements(pipe, + indexResource, + indexSize, + indexBias, + minIndex, + maxIndex, + mode, + start, + count); + + rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_AFTER); + pipe_mutex_unlock(rb_pipe->draw_mutex); +} + +static struct pipe_query * +rbug_create_query(struct pipe_context *_pipe, + unsigned query_type) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + return pipe->create_query(pipe, + query_type); +} + +static void +rbug_destroy_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->destroy_query(pipe, + query); +} + +static void +rbug_begin_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->begin_query(pipe, + query); +} + +static void +rbug_end_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->end_query(pipe, + query); +} + +static boolean +rbug_get_query_result(struct pipe_context *_pipe, + struct pipe_query *query, + boolean wait, + uint64_t *result) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + return pipe->get_query_result(pipe, + query, + wait, + result); +} + +static void * +rbug_create_blend_state(struct pipe_context *_pipe, + const struct pipe_blend_state *blend) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + return pipe->create_blend_state(pipe, + blend); +} + +static void +rbug_bind_blend_state(struct pipe_context *_pipe, + void *blend) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->bind_blend_state(pipe, + blend); +} + +static void +rbug_delete_blend_state(struct pipe_context *_pipe, + void *blend) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->delete_blend_state(pipe, + blend); +} + +static void * +rbug_create_sampler_state(struct pipe_context *_pipe, + const struct pipe_sampler_state *sampler) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + return pipe->create_sampler_state(pipe, + sampler); +} + +static void +rbug_bind_fragment_sampler_states(struct pipe_context *_pipe, + unsigned num_samplers, + void **samplers) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->bind_fragment_sampler_states(pipe, + num_samplers, + samplers); +} + +static void +rbug_bind_vertex_sampler_states(struct pipe_context *_pipe, + unsigned num_samplers, + void **samplers) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->bind_vertex_sampler_states(pipe, + num_samplers, + samplers); +} + +static void +rbug_delete_sampler_state(struct pipe_context *_pipe, + void *sampler) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->delete_sampler_state(pipe, + sampler); +} + +static void * +rbug_create_rasterizer_state(struct pipe_context *_pipe, + const struct pipe_rasterizer_state *rasterizer) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + return pipe->create_rasterizer_state(pipe, + rasterizer); +} + +static void +rbug_bind_rasterizer_state(struct pipe_context *_pipe, + void *rasterizer) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->bind_rasterizer_state(pipe, + rasterizer); +} + +static void +rbug_delete_rasterizer_state(struct pipe_context *_pipe, + void *rasterizer) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->delete_rasterizer_state(pipe, + rasterizer); +} + +static void * +rbug_create_depth_stencil_alpha_state(struct pipe_context *_pipe, + const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + return pipe->create_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); +} + +static void +rbug_bind_depth_stencil_alpha_state(struct pipe_context *_pipe, + void *depth_stencil_alpha) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->bind_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); +} + +static void +rbug_delete_depth_stencil_alpha_state(struct pipe_context *_pipe, + void *depth_stencil_alpha) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->delete_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); +} + +static void * +rbug_create_fs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *state) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *result; + + result = pipe->create_fs_state(pipe, state); + if (!result) + return NULL; + + return rbug_shader_create(rb_pipe, state, result, RBUG_SHADER_FRAGMENT); +} + +static void +rbug_bind_fs_state(struct pipe_context *_pipe, + void *_fs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *fs; + + fs = rbug_shader_unwrap(_fs); + rb_pipe->curr.fs = rbug_shader(_fs); + pipe->bind_fs_state(pipe, + fs); +} + +static void +rbug_delete_fs_state(struct pipe_context *_pipe, + void *_fs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_shader *rb_shader = rbug_shader(_fs); + + rbug_shader_destroy(rb_pipe, rb_shader); +} + +static void * +rbug_create_vs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *state) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *result; + + result = pipe->create_vs_state(pipe, state); + if (!result) + return NULL; + + return rbug_shader_create(rb_pipe, state, result, RBUG_SHADER_VERTEX); +} + +static void +rbug_bind_vs_state(struct pipe_context *_pipe, + void *_vs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *vs; + + vs = rbug_shader_unwrap(_vs); + rb_pipe->curr.vs = rbug_shader(_vs); + pipe->bind_vs_state(pipe, + vs); +} + +static void +rbug_delete_vs_state(struct pipe_context *_pipe, + void *_vs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_shader *rb_shader = rbug_shader(_vs); + + rbug_shader_destroy(rb_pipe, rb_shader); +} + +static void * +rbug_create_gs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *state) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *result; + + result = pipe->create_gs_state(pipe, state); + if (!result) + return NULL; + + return rbug_shader_create(rb_pipe, state, result, RBUG_SHADER_GEOM); +} + +static void +rbug_bind_gs_state(struct pipe_context *_pipe, + void *_gs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *gs; + + gs = rbug_shader_unwrap(_gs); + rb_pipe->curr.gs = rbug_shader(_gs); + pipe->bind_gs_state(pipe, + gs); +} + +static void +rbug_delete_gs_state(struct pipe_context *_pipe, + void *_gs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_shader *rb_shader = rbug_shader(_gs); + + rbug_shader_destroy(rb_pipe, rb_shader); +} + +static void * +rbug_create_vertex_elements_state(struct pipe_context *_pipe, + unsigned num_elements, + const struct pipe_vertex_element *vertex_elements) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + return pipe->create_vertex_elements_state(pipe, + num_elements, + vertex_elements); +} + +static void +rbug_bind_vertex_elements_state(struct pipe_context *_pipe, + void *velems) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->bind_vertex_elements_state(pipe, + velems); +} + +static void +rbug_delete_vertex_elements_state(struct pipe_context *_pipe, + void *velems) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->delete_vertex_elements_state(pipe, + velems); +} + +static void +rbug_set_blend_color(struct pipe_context *_pipe, + const struct pipe_blend_color *blend_color) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->set_blend_color(pipe, + blend_color); +} + +static void +rbug_set_stencil_ref(struct pipe_context *_pipe, + const struct pipe_stencil_ref *stencil_ref) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->set_stencil_ref(pipe, + stencil_ref); +} + +static void +rbug_set_clip_state(struct pipe_context *_pipe, + const struct pipe_clip_state *clip) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->set_clip_state(pipe, + clip); +} + +static void +rbug_set_constant_buffer(struct pipe_context *_pipe, + uint shader, + uint index, + struct pipe_resource *_resource) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *unwrapped_resource; + struct pipe_resource *resource = NULL; + + /* XXX hmm? unwrap the input state */ + if (_resource) { + unwrapped_resource = rbug_resource_unwrap(_resource); + resource = unwrapped_resource; + } + + pipe->set_constant_buffer(pipe, + shader, + index, + resource); +} + +static void +rbug_set_framebuffer_state(struct pipe_context *_pipe, + const struct pipe_framebuffer_state *_state) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_framebuffer_state unwrapped_state; + struct pipe_framebuffer_state *state = NULL; + unsigned i; + + rb_pipe->curr.nr_cbufs = 0; + memset(rb_pipe->curr.cbufs, 0, sizeof(rb_pipe->curr.cbufs)); + + /* unwrap the input state */ + if (_state) { + memcpy(&unwrapped_state, _state, sizeof(unwrapped_state)); + + rb_pipe->curr.nr_cbufs = _state->nr_cbufs; + for(i = 0; i < _state->nr_cbufs; i++) { + unwrapped_state.cbufs[i] = rbug_surface_unwrap(_state->cbufs[i]); + if (_state->cbufs[i]) + rb_pipe->curr.cbufs[i] = rbug_resource(_state->cbufs[i]->texture); + } + unwrapped_state.zsbuf = rbug_surface_unwrap(_state->zsbuf); + state = &unwrapped_state; + } + + pipe->set_framebuffer_state(pipe, + state); +} + +static void +rbug_set_polygon_stipple(struct pipe_context *_pipe, + const struct pipe_poly_stipple *poly_stipple) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->set_polygon_stipple(pipe, + poly_stipple); +} + +static void +rbug_set_scissor_state(struct pipe_context *_pipe, + const struct pipe_scissor_state *scissor) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->set_scissor_state(pipe, + scissor); +} + +static void +rbug_set_viewport_state(struct pipe_context *_pipe, + const struct pipe_viewport_state *viewport) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->set_viewport_state(pipe, + viewport); +} + +static void +rbug_set_fragment_sampler_views(struct pipe_context *_pipe, + unsigned num, + struct pipe_sampler_view **_views) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_sampler_view *unwrapped_views[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view **views = NULL; + unsigned i; + + rb_pipe->curr.num_fs_views = 0; + memset(rb_pipe->curr.fs_views, 0, sizeof(rb_pipe->curr.fs_views)); + memset(rb_pipe->curr.fs_texs, 0, sizeof(rb_pipe->curr.fs_texs)); + memset(unwrapped_views, 0, sizeof(unwrapped_views)); + + if (_views) { + rb_pipe->curr.num_fs_views = num; + for (i = 0; i < num; i++) { + rb_pipe->curr.fs_views[i] = rbug_sampler_view(_views[i]); + rb_pipe->curr.fs_texs[i] = rbug_resource(_views[i] ? _views[i]->texture : NULL); + unwrapped_views[i] = rbug_sampler_view_unwrap(_views[i]); + } + views = unwrapped_views; + } + + pipe->set_fragment_sampler_views(pipe, num, views); +} + +static void +rbug_set_vertex_sampler_views(struct pipe_context *_pipe, + unsigned num, + struct pipe_sampler_view **_views) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_sampler_view *unwrapped_views[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_view **views = NULL; + unsigned i; + + rb_pipe->curr.num_vs_views = 0; + memset(rb_pipe->curr.vs_views, 0, sizeof(rb_pipe->curr.vs_views)); + memset(rb_pipe->curr.vs_texs, 0, sizeof(rb_pipe->curr.vs_texs)); + memset(unwrapped_views, 0, sizeof(unwrapped_views)); + + if (_views) { + rb_pipe->curr.num_vs_views = num; + for (i = 0; i < num; i++) { + rb_pipe->curr.vs_views[i] = rbug_sampler_view(_views[i]); + rb_pipe->curr.vs_texs[i] = rbug_resource(_views[i]->texture); + unwrapped_views[i] = rbug_sampler_view_unwrap(_views[i]); + } + views = unwrapped_views; + } + + pipe->set_vertex_sampler_views(pipe, num, views); +} + +static void +rbug_set_vertex_buffers(struct pipe_context *_pipe, + unsigned num_buffers, + const struct pipe_vertex_buffer *_buffers) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_vertex_buffer unwrapped_buffers[PIPE_MAX_SHADER_INPUTS]; + struct pipe_vertex_buffer *buffers = NULL; + unsigned i; + + if (num_buffers) { + memcpy(unwrapped_buffers, _buffers, num_buffers * sizeof(*_buffers)); + for (i = 0; i < num_buffers; i++) + unwrapped_buffers[i].buffer = rbug_resource_unwrap(_buffers[i].buffer); + buffers = unwrapped_buffers; + } + + pipe->set_vertex_buffers(pipe, + num_buffers, + buffers); +} +static void +rbug_surface_copy(struct pipe_context *_pipe, + struct pipe_surface *_dst, + unsigned dstx, + unsigned dsty, + struct pipe_surface *_src, + unsigned srcx, + unsigned srcy, + unsigned width, + unsigned height) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_surface *rb_surface_dst = rbug_surface(_dst); + struct rbug_surface *rb_surface_src = rbug_surface(_src); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_surface *dst = rb_surface_dst->surface; + struct pipe_surface *src = rb_surface_src->surface; + + pipe->surface_copy(pipe, + dst, + dstx, + dsty, + src, + srcx, + srcy, + width, + height); +} + +static void +rbug_surface_fill(struct pipe_context *_pipe, + struct pipe_surface *_dst, + unsigned dstx, + unsigned dsty, + unsigned width, + unsigned height, + unsigned value) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_surface *rb_surface_dst = rbug_surface(_dst); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_surface *dst = rb_surface_dst->surface; + + pipe->surface_fill(pipe, + dst, + dstx, + dsty, + width, + height, + value); +} + +static void +rbug_clear(struct pipe_context *_pipe, + unsigned buffers, + const float *rgba, + double depth, + unsigned stencil) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->clear(pipe, + buffers, + rgba, + depth, + stencil); +} + +static void +rbug_flush(struct pipe_context *_pipe, + unsigned flags, + struct pipe_fence_handle **fence) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe->flush(pipe, + flags, + fence); +} + +static unsigned int +rbug_is_resource_referenced(struct pipe_context *_pipe, + struct pipe_resource *_resource, + unsigned face, + unsigned level) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + + return pipe->is_resource_referenced(pipe, + resource, + face, + level); +} + +static struct pipe_sampler_view * +rbug_context_create_sampler_view(struct pipe_context *_pipe, + struct pipe_resource *_resource, + const struct pipe_sampler_view *templ) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + struct pipe_sampler_view *result; + + result = pipe->create_sampler_view(pipe, + resource, + templ); + + if (result) + return rbug_sampler_view_create(rb_pipe, rb_resource, result); + return NULL; +} + +static void +rbug_context_sampler_view_destroy(struct pipe_context *_pipe, + struct pipe_sampler_view *_view) +{ + rbug_sampler_view_destroy(rbug_context(_pipe), + rbug_sampler_view(_view)); +} + +static struct pipe_transfer * +rbug_context_get_transfer(struct pipe_context *_context, + struct pipe_resource *_resource, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box) +{ + struct rbug_context *rb_pipe = rbug_context(_context); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + struct pipe_transfer *result; + + result = context->get_transfer(context, + resource, + sr, + usage, + box); + + if (result) + return rbug_transfer_create(rb_pipe, rb_resource, result); + return NULL; +} + +static void +rbug_context_transfer_destroy(struct pipe_context *_pipe, + struct pipe_transfer *_transfer) +{ + rbug_transfer_destroy(rbug_context(_pipe), + rbug_transfer(_transfer)); +} + +static void * +rbug_context_transfer_map(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct rbug_context *rb_pipe = rbug_context(_context); + struct rbug_transfer *rb_transfer = rbug_transfer(_transfer); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_transfer *transfer = rb_transfer->transfer; + + return context->transfer_map(context, + transfer); +} + + + +static void +rbug_context_transfer_flush_region(struct pipe_context *_context, + struct pipe_transfer *_transfer, + const struct pipe_box *box) +{ + struct rbug_context *rb_pipe = rbug_context(_context); + struct rbug_transfer *rb_transfer = rbug_transfer(_transfer); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_transfer *transfer = rb_transfer->transfer; + + context->transfer_flush_region(context, + transfer, + box); +} + + +static void +rbug_context_transfer_unmap(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct rbug_context *rb_pipe = rbug_context(_context); + struct rbug_transfer *rb_transfer = rbug_transfer(_transfer); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_transfer *transfer = rb_transfer->transfer; + + context->transfer_unmap(context, + transfer); +} + + +static void +rbug_context_transfer_inline_write(struct pipe_context *_context, + struct pipe_resource *_resource, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned slice_stride) +{ + struct rbug_context *rb_pipe = rbug_context(_context); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + + context->transfer_inline_write(context, + resource, + sr, + usage, + box, + data, + stride, + slice_stride); +} + + +struct pipe_context * +rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) +{ + struct rbug_context *rb_pipe; + struct rbug_screen *rb_screen = rbug_screen(_screen); + + if (!rb_screen) + return NULL; + + rb_pipe = CALLOC_STRUCT(rbug_context); + if (!rb_pipe) + return NULL; + + pipe_mutex_init(rb_pipe->draw_mutex); + pipe_condvar_init(rb_pipe->draw_cond); + pipe_mutex_init(rb_pipe->call_mutex); + pipe_mutex_init(rb_pipe->list_mutex); + make_empty_list(&rb_pipe->shaders); + + rb_pipe->base.winsys = NULL; + rb_pipe->base.screen = _screen; + rb_pipe->base.priv = pipe->priv; /* expose wrapped data */ + rb_pipe->base.draw = NULL; + + rb_pipe->base.destroy = rbug_destroy; + rb_pipe->base.draw_arrays = rbug_draw_arrays; + rb_pipe->base.draw_elements = rbug_draw_elements; + rb_pipe->base.draw_range_elements = rbug_draw_range_elements; + rb_pipe->base.create_query = rbug_create_query; + rb_pipe->base.destroy_query = rbug_destroy_query; + rb_pipe->base.begin_query = rbug_begin_query; + rb_pipe->base.end_query = rbug_end_query; + rb_pipe->base.get_query_result = rbug_get_query_result; + rb_pipe->base.create_blend_state = rbug_create_blend_state; + rb_pipe->base.bind_blend_state = rbug_bind_blend_state; + rb_pipe->base.delete_blend_state = rbug_delete_blend_state; + rb_pipe->base.create_sampler_state = rbug_create_sampler_state; + rb_pipe->base.bind_fragment_sampler_states = rbug_bind_fragment_sampler_states; + rb_pipe->base.bind_vertex_sampler_states = rbug_bind_vertex_sampler_states; + rb_pipe->base.delete_sampler_state = rbug_delete_sampler_state; + rb_pipe->base.create_rasterizer_state = rbug_create_rasterizer_state; + rb_pipe->base.bind_rasterizer_state = rbug_bind_rasterizer_state; + rb_pipe->base.delete_rasterizer_state = rbug_delete_rasterizer_state; + rb_pipe->base.create_depth_stencil_alpha_state = rbug_create_depth_stencil_alpha_state; + rb_pipe->base.bind_depth_stencil_alpha_state = rbug_bind_depth_stencil_alpha_state; + rb_pipe->base.delete_depth_stencil_alpha_state = rbug_delete_depth_stencil_alpha_state; + rb_pipe->base.create_fs_state = rbug_create_fs_state; + rb_pipe->base.bind_fs_state = rbug_bind_fs_state; + rb_pipe->base.delete_fs_state = rbug_delete_fs_state; + rb_pipe->base.create_vs_state = rbug_create_vs_state; + rb_pipe->base.bind_vs_state = rbug_bind_vs_state; + rb_pipe->base.delete_vs_state = rbug_delete_vs_state; + rb_pipe->base.create_gs_state = rbug_create_gs_state; + rb_pipe->base.bind_gs_state = rbug_bind_gs_state; + rb_pipe->base.delete_gs_state = rbug_delete_gs_state; + rb_pipe->base.create_vertex_elements_state = rbug_create_vertex_elements_state; + rb_pipe->base.bind_vertex_elements_state = rbug_bind_vertex_elements_state; + rb_pipe->base.delete_vertex_elements_state = rbug_delete_vertex_elements_state; + rb_pipe->base.set_blend_color = rbug_set_blend_color; + rb_pipe->base.set_stencil_ref = rbug_set_stencil_ref; + rb_pipe->base.set_clip_state = rbug_set_clip_state; + rb_pipe->base.set_constant_buffer = rbug_set_constant_buffer; + rb_pipe->base.set_framebuffer_state = rbug_set_framebuffer_state; + rb_pipe->base.set_polygon_stipple = rbug_set_polygon_stipple; + rb_pipe->base.set_scissor_state = rbug_set_scissor_state; + rb_pipe->base.set_viewport_state = rbug_set_viewport_state; + rb_pipe->base.set_fragment_sampler_views = rbug_set_fragment_sampler_views; + rb_pipe->base.set_vertex_sampler_views = rbug_set_vertex_sampler_views; + rb_pipe->base.set_vertex_buffers = rbug_set_vertex_buffers; + rb_pipe->base.surface_copy = rbug_surface_copy; + rb_pipe->base.surface_fill = rbug_surface_fill; + rb_pipe->base.clear = rbug_clear; + rb_pipe->base.flush = rbug_flush; + rb_pipe->base.is_resource_referenced = rbug_is_resource_referenced; + rb_pipe->base.create_sampler_view = rbug_context_create_sampler_view; + rb_pipe->base.sampler_view_destroy = rbug_context_sampler_view_destroy; + rb_pipe->base.get_transfer = rbug_context_get_transfer; + rb_pipe->base.transfer_destroy = rbug_context_transfer_destroy; + rb_pipe->base.transfer_map = rbug_context_transfer_map; + rb_pipe->base.transfer_unmap = rbug_context_transfer_unmap; + rb_pipe->base.transfer_flush_region = rbug_context_transfer_flush_region; + rb_pipe->base.transfer_inline_write = rbug_context_transfer_inline_write; + + rb_pipe->pipe = pipe; + + rbug_screen_add_to_list(rb_screen, contexts, rb_pipe); + + return &rb_pipe->base; +} diff --git a/src/gallium/drivers/rbug/rbug_context.h b/src/gallium/drivers/rbug/rbug_context.h new file mode 100644 index 00000000000..80c803da83f --- /dev/null +++ b/src/gallium/drivers/rbug/rbug_context.h @@ -0,0 +1,111 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * 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 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 VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef RBUG_CONTEXT_H +#define RBUG_CONTEXT_H + +#include "pipe/p_state.h" +#include "pipe/p_context.h" + +#include "rbug_screen.h" + + +struct rbug_context { + struct pipe_context base; /**< base class */ + + struct pipe_context *pipe; + + struct rbug_list list; + + /* call locking */ + pipe_mutex call_mutex; + + /* current state */ + struct { + struct rbug_shader *fs; + struct rbug_shader *vs; + struct rbug_shader *gs; + + struct rbug_sampler_view *fs_views[PIPE_MAX_SAMPLERS]; + struct rbug_resource *fs_texs[PIPE_MAX_SAMPLERS]; + unsigned num_fs_views; + + struct rbug_sampler_view *vs_views[PIPE_MAX_VERTEX_SAMPLERS]; + struct rbug_resource *vs_texs[PIPE_MAX_VERTEX_SAMPLERS]; + unsigned num_vs_views; + + unsigned nr_cbufs; + struct rbug_resource *cbufs[PIPE_MAX_COLOR_BUFS]; + struct rbug_resource *zsbuf; + } curr; + + /* draw locking */ + pipe_mutex draw_mutex; + pipe_condvar draw_cond; + unsigned draw_num_rules; + int draw_blocker; + int draw_blocked; + + struct { + struct rbug_shader *fs; + struct rbug_shader *vs; + + struct rbug_resource *texture; + struct rbug_resource *surf; + + int blocker; + } draw_rule; + + /* list of state objects */ + pipe_mutex list_mutex; + unsigned num_shaders; + struct rbug_list shaders; +}; + +static INLINE struct rbug_context * +rbug_context(struct pipe_context *pipe) +{ + return (struct rbug_context *)pipe; +} + + +/********************************************************** + * rbug_context.c + */ + +struct pipe_context * +rbug_context_create(struct pipe_screen *screen, struct pipe_context *pipe); + + +/********************************************************** + * rbug_core.c + */ + +void rbug_notify_draw_blocked(struct rbug_context *rb_context); + + +#endif /* RBUG_CONTEXT_H */ diff --git a/src/gallium/drivers/rbug/rbug_core.c b/src/gallium/drivers/rbug/rbug_core.c new file mode 100644 index 00000000000..f1aab3869b5 --- /dev/null +++ b/src/gallium/drivers/rbug/rbug_core.c @@ -0,0 +1,890 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * 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 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 VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "os/os_thread.h" +#include "util/u_format.h" +#include "util/u_string.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" +#include "util/u_network.h" +#include "os/os_time.h" + +#include "tgsi/tgsi_parse.h" + +#include "rbug_context.h" +#include "rbug_objects.h" + +#include "rbug/rbug.h" + +#include <errno.h> + +#define U642VOID(x) ((void *)(unsigned long)(x)) +#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) + +#define container_of(ptr, type, field) \ + (type*)((char*)ptr - offsetof(type, field)) + +struct rbug_rbug +{ + struct rbug_screen *rb_screen; + struct rbug_connection *con; + pipe_thread thread; + boolean running; +}; + +PIPE_THREAD_ROUTINE(rbug_thread, void_rbug); + + +/********************************************************** + * Helper functions + */ + + +static struct rbug_context * +rbug_get_context_locked(struct rbug_screen *rb_screen, rbug_context_t ctx) +{ + struct rbug_context *rb_context = NULL; + struct rbug_list *ptr; + + foreach(ptr, &rb_screen->contexts) { + rb_context = container_of(ptr, struct rbug_context, list); + if (ctx == VOID2U64(rb_context)) + break; + rb_context = NULL; + } + + return rb_context; +} + +static struct rbug_shader * +rbug_get_shader_locked(struct rbug_context *rb_context, rbug_shader_t shdr) +{ + struct rbug_shader *tr_shdr = NULL; + struct rbug_list *ptr; + + foreach(ptr, &rb_context->shaders) { + tr_shdr = container_of(ptr, struct rbug_shader, list); + if (shdr == VOID2U64(tr_shdr)) + break; + tr_shdr = NULL; + } + + return tr_shdr; +} + +static void * +rbug_shader_create_locked(struct pipe_context *pipe, + struct rbug_shader *rb_shader, + struct tgsi_token *tokens) +{ + void *state = NULL; + struct pipe_shader_state pss = { 0 }; + pss.tokens = tokens; + + switch(rb_shader->type) { + case RBUG_SHADER_FRAGMENT: + state = pipe->create_fs_state(pipe, &pss); + break; + case RBUG_SHADER_VERTEX: + state = pipe->create_vs_state(pipe, &pss); + break; + case RBUG_SHADER_GEOM: + state = pipe->create_gs_state(pipe, &pss); + break; + default: + assert(0); + break; + } + + return state; +} + +static void +rbug_shader_bind_locked(struct pipe_context *pipe, + struct rbug_shader *rb_shader, + void *state) +{ + switch(rb_shader->type) { + case RBUG_SHADER_FRAGMENT: + pipe->bind_fs_state(pipe, state); + break; + case RBUG_SHADER_VERTEX: + pipe->bind_vs_state(pipe, state); + break; + case RBUG_SHADER_GEOM: + pipe->bind_gs_state(pipe, state); + break; + default: + assert(0); + break; + } +} + +static void +rbug_shader_delete_locked(struct pipe_context *pipe, + struct rbug_shader *rb_shader, + void *state) +{ + switch(rb_shader->type) { + case RBUG_SHADER_FRAGMENT: + pipe->delete_fs_state(pipe, state); + break; + case RBUG_SHADER_VERTEX: + pipe->delete_vs_state(pipe, state); + break; + case RBUG_SHADER_GEOM: + pipe->delete_gs_state(pipe, state); + break; + default: + assert(0); + break; + } +} + +/************************************************ + * Request handler functions + */ + + +static int +rbug_texture_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_resource *tr_tex = NULL; + struct rbug_list *ptr; + rbug_texture_t *texs; + int i = 0; + + pipe_mutex_lock(rb_screen->list_mutex); + texs = MALLOC(rb_screen->num_resources * sizeof(rbug_texture_t)); + foreach(ptr, &rb_screen->resources) { + tr_tex = container_of(ptr, struct rbug_resource, list); + texs[i++] = VOID2U64(tr_tex); + } + pipe_mutex_unlock(rb_screen->list_mutex); + + rbug_send_texture_list_reply(tr_rbug->con, serial, texs, i, NULL); + FREE(texs); + + return 0; +} + +static int +rbug_texture_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_resource *tr_tex = NULL; + struct rbug_proto_texture_info *gpti = (struct rbug_proto_texture_info *)header; + struct rbug_list *ptr; + struct pipe_resource *t; + + pipe_mutex_lock(rb_screen->list_mutex); + foreach(ptr, &rb_screen->resources) { + tr_tex = container_of(ptr, struct rbug_resource, list); + if (gpti->texture == VOID2U64(tr_tex)) + break; + tr_tex = NULL; + } + + if (!tr_tex) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + t = tr_tex->resource; + rbug_send_texture_info_reply(tr_rbug->con, serial, + t->target, t->format, + &t->width0, 1, + &t->height0, 1, + &t->depth0, 1, + util_format_get_blockwidth(t->format), + util_format_get_blockheight(t->format), + util_format_get_blocksize(t->format), + t->last_level, + t->nr_samples, + t->bind, + NULL); + + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; +} + +static int +rbug_texture_read(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_resource *tr_tex = NULL; + struct rbug_list *ptr; + + struct pipe_context *context = rb_screen->private_context; + struct pipe_resource *tex; + struct pipe_transfer *t; + + void *map; + + pipe_mutex_lock(rb_screen->list_mutex); + foreach(ptr, &rb_screen->resources) { + tr_tex = container_of(ptr, struct rbug_resource, list); + if (gptr->texture == VOID2U64(tr_tex)) + break; + tr_tex = NULL; + } + + if (!tr_tex) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + tex = tr_tex->resource; + t = pipe_get_transfer(context, tex, + gptr->face, gptr->level, gptr->zslice, + PIPE_TRANSFER_READ, + gptr->x, gptr->y, gptr->w, gptr->h); + + map = context->transfer_map(context, t); + + rbug_send_texture_read_reply(tr_rbug->con, serial, + t->resource->format, + util_format_get_blockwidth(t->resource->format), + util_format_get_blockheight(t->resource->format), + util_format_get_blocksize(t->resource->format), + (uint8_t*)map, + t->stride * util_format_get_nblocksy(t->resource->format, + t->box.height), + t->stride, + NULL); + + context->transfer_unmap(context, t); + context->transfer_destroy(context, t); + + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_list *ptr; + struct rbug_context *rb_context = NULL; + rbug_context_t *ctxs; + int i = 0; + + pipe_mutex_lock(rb_screen->list_mutex); + ctxs = MALLOC(rb_screen->num_contexts * sizeof(rbug_context_t)); + foreach(ptr, &rb_screen->contexts) { + rb_context = container_of(ptr, struct rbug_context, list); + ctxs[i++] = VOID2U64(rb_context); + } + pipe_mutex_unlock(rb_screen->list_mutex); + + rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL); + FREE(ctxs); + + return 0; +} + +static int +rbug_context_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS]; + rbug_texture_t texs[PIPE_MAX_SAMPLERS]; + int i; + + pipe_mutex_lock(rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, info->context); + + if (!rb_context) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + /* protect the pipe context */ + pipe_mutex_lock(rb_context->draw_mutex); + pipe_mutex_lock(rb_context->call_mutex); + + for (i = 0; i < rb_context->curr.nr_cbufs; i++) + cbufs[i] = VOID2U64(rb_context->curr.cbufs[i]); + + for (i = 0; i < rb_context->curr.num_fs_views; i++) + texs[i] = VOID2U64(rb_context->curr.fs_texs[i]); + + rbug_send_context_info_reply(tr_rbug->con, serial, + VOID2U64(rb_context->curr.vs), VOID2U64(rb_context->curr.fs), + texs, rb_context->curr.num_fs_views, + cbufs, rb_context->curr.nr_cbufs, + VOID2U64(rb_context->curr.zsbuf), + rb_context->draw_blocker, rb_context->draw_blocked, NULL); + + pipe_mutex_unlock(rb_context->call_mutex); + pipe_mutex_unlock(rb_context->draw_mutex); + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_draw_block(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_block *block = (struct rbug_proto_context_draw_block *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + + pipe_mutex_lock(rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, block->context); + + if (!rb_context) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(rb_context->draw_mutex); + rb_context->draw_blocker |= block->block; + pipe_mutex_unlock(rb_context->draw_mutex); + + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_draw_step(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_step *step = (struct rbug_proto_context_draw_step *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + + pipe_mutex_lock(rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, step->context); + + if (!rb_context) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(rb_context->draw_mutex); + if (rb_context->draw_blocked & RBUG_BLOCK_RULE) { + if (step->step & RBUG_BLOCK_RULE) + rb_context->draw_blocked &= ~RBUG_BLOCK_MASK; + } else { + rb_context->draw_blocked &= ~step->step; + } + pipe_mutex_unlock(rb_context->draw_mutex); + +#ifdef PIPE_THREAD_HAVE_CONDVAR + pipe_condvar_broadcast(rb_context->draw_cond); +#endif + + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_draw_unblock(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_unblock *unblock = (struct rbug_proto_context_draw_unblock *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + + pipe_mutex_lock(rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, unblock->context); + + if (!rb_context) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(rb_context->draw_mutex); + if (rb_context->draw_blocked & RBUG_BLOCK_RULE) { + if (unblock->unblock & RBUG_BLOCK_RULE) + rb_context->draw_blocked &= ~RBUG_BLOCK_MASK; + } else { + rb_context->draw_blocked &= ~unblock->unblock; + } + rb_context->draw_blocker &= ~unblock->unblock; + pipe_mutex_unlock(rb_context->draw_mutex); + +#ifdef PIPE_THREAD_HAVE_CONDVAR + pipe_condvar_broadcast(rb_context->draw_cond); +#endif + + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_draw_rule(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_rule *rule = (struct rbug_proto_context_draw_rule *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + + pipe_mutex_lock(rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, rule->context); + + if (!rb_context) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(rb_context->draw_mutex); + rb_context->draw_rule.vs = U642VOID(rule->vertex); + rb_context->draw_rule.fs = U642VOID(rule->fragment); + rb_context->draw_rule.texture = U642VOID(rule->texture); + rb_context->draw_rule.surf = U642VOID(rule->surface); + rb_context->draw_rule.blocker = rule->block; + rb_context->draw_blocker |= RBUG_BLOCK_RULE; + pipe_mutex_unlock(rb_context->draw_mutex); + +#ifdef PIPE_THREAD_HAVE_CONDVAR + pipe_condvar_broadcast(rb_context->draw_cond); +#endif + + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_flush(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_flush *flush = (struct rbug_proto_context_flush *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + + pipe_mutex_lock(rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, flush->context); + + if (!rb_context) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + /* protect the pipe context */ + pipe_mutex_lock(rb_context->call_mutex); + + rb_context->pipe->flush(rb_context->pipe, flush->flags, NULL); + + pipe_mutex_unlock(rb_context->call_mutex); + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; +} + +static int +rbug_shader_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_shader_list *list = (struct rbug_proto_shader_list *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + struct rbug_shader *tr_shdr = NULL; + struct rbug_list *ptr; + rbug_shader_t *shdrs; + int i = 0; + + pipe_mutex_lock(rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, list->context); + + if (!rb_context) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(rb_context->list_mutex); + shdrs = MALLOC(rb_context->num_shaders * sizeof(rbug_shader_t)); + foreach(ptr, &rb_context->shaders) { + tr_shdr = container_of(ptr, struct rbug_shader, list); + shdrs[i++] = VOID2U64(tr_shdr); + } + + pipe_mutex_unlock(rb_context->list_mutex); + pipe_mutex_unlock(rb_screen->list_mutex); + + rbug_send_shader_list_reply(tr_rbug->con, serial, shdrs, i, NULL); + FREE(shdrs); + + return 0; +} + +static int +rbug_shader_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_shader_info *info = (struct rbug_proto_shader_info *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + struct rbug_shader *tr_shdr = NULL; + unsigned original_len; + unsigned replaced_len; + + pipe_mutex_lock(rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, info->context); + + if (!rb_context) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(rb_context->list_mutex); + + tr_shdr = rbug_get_shader_locked(rb_context, info->shader); + + if (!tr_shdr) { + pipe_mutex_unlock(rb_context->list_mutex); + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + /* just in case */ + assert(sizeof(struct tgsi_token) == 4); + + original_len = tgsi_num_tokens(tr_shdr->tokens); + if (tr_shdr->replaced_tokens) + replaced_len = tgsi_num_tokens(tr_shdr->replaced_tokens); + else + replaced_len = 0; + + rbug_send_shader_info_reply(tr_rbug->con, serial, + (uint32_t*)tr_shdr->tokens, original_len, + (uint32_t*)tr_shdr->replaced_tokens, replaced_len, + tr_shdr->disabled, + NULL); + + pipe_mutex_unlock(rb_context->list_mutex); + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; +} + +static int +rbug_shader_disable(struct rbug_rbug *tr_rbug, struct rbug_header *header) +{ + struct rbug_proto_shader_disable *dis = (struct rbug_proto_shader_disable *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + struct rbug_shader *tr_shdr = NULL; + + pipe_mutex_lock(rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, dis->context); + + if (!rb_context) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(rb_context->list_mutex); + + tr_shdr = rbug_get_shader_locked(rb_context, dis->shader); + + if (!tr_shdr) { + pipe_mutex_unlock(rb_context->list_mutex); + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + tr_shdr->disabled = dis->disable; + + pipe_mutex_unlock(rb_context->list_mutex); + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; +} + +static int +rbug_shader_replace(struct rbug_rbug *tr_rbug, struct rbug_header *header) +{ + struct rbug_proto_shader_replace *rep = (struct rbug_proto_shader_replace *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + struct rbug_shader *tr_shdr = NULL; + struct pipe_context *pipe = NULL; + void *state; + + pipe_mutex_lock(rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, rep->context); + + if (!rb_context) { + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(rb_context->list_mutex); + + tr_shdr = rbug_get_shader_locked(rb_context, rep->shader); + + if (!tr_shdr) { + pipe_mutex_unlock(rb_context->list_mutex); + pipe_mutex_unlock(rb_screen->list_mutex); + return -ESRCH; + } + + /* protect the pipe context */ + pipe_mutex_lock(rb_context->call_mutex); + + pipe = rb_context->pipe; + + /* remove old replaced shader */ + if (tr_shdr->replaced_shader) { + /* if this shader is bound rebind the original shader */ + if (rb_context->curr.fs == tr_shdr || rb_context->curr.vs == tr_shdr) + rbug_shader_bind_locked(pipe, tr_shdr, tr_shdr->shader); + + FREE(tr_shdr->replaced_tokens); + rbug_shader_delete_locked(pipe, tr_shdr, tr_shdr->replaced_shader); + tr_shdr->replaced_shader = NULL; + tr_shdr->replaced_tokens = NULL; + } + + /* empty inputs means restore old which we did above */ + if (rep->tokens_len == 0) + goto out; + + tr_shdr->replaced_tokens = tgsi_dup_tokens((struct tgsi_token *)rep->tokens); + if (!tr_shdr->replaced_tokens) + goto err; + + state = rbug_shader_create_locked(pipe, tr_shdr, tr_shdr->replaced_tokens); + if (!state) + goto err; + + /* bind new shader if the shader is currently a bound */ + if (rb_context->curr.fs == tr_shdr || rb_context->curr.vs == tr_shdr) + rbug_shader_bind_locked(pipe, tr_shdr, state); + + /* save state */ + tr_shdr->replaced_shader = state; + +out: + pipe_mutex_unlock(rb_context->call_mutex); + pipe_mutex_unlock(rb_context->list_mutex); + pipe_mutex_unlock(rb_screen->list_mutex); + + return 0; + +err: + FREE(tr_shdr->replaced_tokens); + tr_shdr->replaced_shader = NULL; + tr_shdr->replaced_tokens = NULL; + + pipe_mutex_unlock(rb_context->call_mutex); + pipe_mutex_unlock(rb_context->list_mutex); + pipe_mutex_unlock(rb_screen->list_mutex); + return -EINVAL; +} + +static boolean +rbug_header(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + int ret = 0; + + switch(header->opcode) { + case RBUG_OP_PING: + rbug_send_ping_reply(tr_rbug->con, serial, NULL); + break; + case RBUG_OP_TEXTURE_LIST: + ret = rbug_texture_list(tr_rbug, header, serial); + break; + case RBUG_OP_TEXTURE_INFO: + ret = rbug_texture_info(tr_rbug, header, serial); + break; + case RBUG_OP_TEXTURE_READ: + ret = rbug_texture_read(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_LIST: + ret = rbug_context_list(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_INFO: + ret = rbug_context_info(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_BLOCK: + ret = rbug_context_draw_block(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_STEP: + ret = rbug_context_draw_step(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_UNBLOCK: + ret = rbug_context_draw_unblock(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_RULE: + ret = rbug_context_draw_rule(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_FLUSH: + ret = rbug_context_flush(tr_rbug, header, serial); + break; + case RBUG_OP_SHADER_LIST: + ret = rbug_shader_list(tr_rbug, header, serial); + break; + case RBUG_OP_SHADER_INFO: + ret = rbug_shader_info(tr_rbug, header, serial); + break; + case RBUG_OP_SHADER_DISABLE: + ret = rbug_shader_disable(tr_rbug, header); + break; + case RBUG_OP_SHADER_REPLACE: + ret = rbug_shader_replace(tr_rbug, header); + break; + default: + debug_printf("%s - unsupported opcode %u\n", __FUNCTION__, header->opcode); + ret = -ENOSYS; + break; + } + rbug_free_header(header); + + if (ret) + rbug_send_error_reply(tr_rbug->con, serial, ret, NULL); + + return TRUE; +} + +static void +rbug_con(struct rbug_rbug *tr_rbug) +{ + struct rbug_header *header; + uint32_t serial; + + debug_printf("%s - connection received\n", __FUNCTION__); + + while(tr_rbug->running) { + header = rbug_get_message(tr_rbug->con, &serial); + if (!header) + break; + + if (!rbug_header(tr_rbug, header, serial)) + break; + } + + debug_printf("%s - connection closed\n", __FUNCTION__); + + rbug_disconnect(tr_rbug->con); + tr_rbug->con = NULL; +} + +PIPE_THREAD_ROUTINE(rbug_thread, void_tr_rbug) +{ + struct rbug_rbug *tr_rbug = void_tr_rbug; + uint16_t port = 13370; + int s = -1; + int c; + + u_socket_init(); + + for (;port <= 13379 && s < 0; port++) + s = u_socket_listen_on_port(port); + + if (s < 0) { + debug_printf("rbug_rbug - failed to listen\n"); + return NULL; + } + + u_socket_block(s, false); + + debug_printf("rbug_rbug - remote debugging listening on port %u\n", --port); + + while(tr_rbug->running) { + os_time_sleep(1); + + c = u_socket_accept(s); + if (c < 0) + continue; + + u_socket_block(c, true); + tr_rbug->con = rbug_from_socket(c); + + rbug_con(tr_rbug); + + u_socket_close(c); + } + + u_socket_close(s); + + u_socket_stop(); + + return NULL; +} + +/********************************************************** + * + */ + +struct rbug_rbug * +rbug_start(struct rbug_screen *rb_screen) +{ + struct rbug_rbug *tr_rbug = CALLOC_STRUCT(rbug_rbug); + if (!tr_rbug) + return NULL; + + tr_rbug->rb_screen = rb_screen; + tr_rbug->running = TRUE; + tr_rbug->thread = pipe_thread_create(rbug_thread, tr_rbug); + + return tr_rbug; +} + +void +rbug_stop(struct rbug_rbug *tr_rbug) +{ + if (!tr_rbug) + return; + + tr_rbug->running = false; + pipe_thread_wait(tr_rbug->thread); + + FREE(tr_rbug); + + return; +} + +void +rbug_notify_draw_blocked(struct rbug_context *rb_context) +{ + struct rbug_screen *rb_screen = rbug_screen(rb_context->base.screen); + struct rbug_rbug *tr_rbug = rb_screen->rbug; + + if (tr_rbug && tr_rbug->con) + rbug_send_context_draw_blocked(tr_rbug->con, + VOID2U64(rb_context), rb_context->draw_blocked, NULL); +} diff --git a/src/gallium/drivers/rbug/rbug_objects.c b/src/gallium/drivers/rbug/rbug_objects.c new file mode 100644 index 00000000000..0979fcff957 --- /dev/null +++ b/src/gallium/drivers/rbug/rbug_objects.c @@ -0,0 +1,247 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * 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 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 VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" + +#include "tgsi/tgsi_parse.h" + +#include "rbug_screen.h" +#include "rbug_objects.h" +#include "rbug_context.h" + + + +struct pipe_resource * +rbug_resource_create(struct rbug_screen *rb_screen, + struct pipe_resource *resource) +{ + struct rbug_resource *rb_resource; + + if(!resource) + goto error; + + assert(resource->screen == rb_screen->screen); + + rb_resource = CALLOC_STRUCT(rbug_resource); + if(!rb_resource) + goto error; + + memcpy(&rb_resource->base, resource, sizeof(struct pipe_resource)); + + pipe_reference_init(&rb_resource->base.reference, 1); + rb_resource->base.screen = &rb_screen->base; + rb_resource->resource = resource; + + rbug_screen_add_to_list(rb_screen, resources, rb_resource); + + return &rb_resource->base; + +error: + pipe_resource_reference(&resource, NULL); + return NULL; +} + +void +rbug_resource_destroy(struct rbug_resource *rb_resource) +{ + struct rbug_screen *rb_screen = rbug_screen(rb_resource->base.screen); + rbug_screen_remove_from_list(rb_screen, resources, rb_resource); + + pipe_resource_reference(&rb_resource->resource, NULL); + FREE(rb_resource); +} + + +struct pipe_surface * +rbug_surface_create(struct rbug_resource *rb_resource, + struct pipe_surface *surface) +{ + struct rbug_surface *rb_surface; + + if(!surface) + goto error; + + assert(surface->texture == rb_resource->resource); + + rb_surface = CALLOC_STRUCT(rbug_surface); + if(!rb_surface) + goto error; + + memcpy(&rb_surface->base, surface, sizeof(struct pipe_surface)); + + pipe_reference_init(&rb_surface->base.reference, 1); + rb_surface->base.texture = NULL; + pipe_resource_reference(&rb_surface->base.texture, &rb_resource->base); + rb_surface->surface = surface; + + return &rb_surface->base; + +error: + pipe_surface_reference(&surface, NULL); + return NULL; +} + +void +rbug_surface_destroy(struct rbug_surface *rb_surface) +{ + pipe_resource_reference(&rb_surface->base.texture, NULL); + pipe_surface_reference(&rb_surface->surface, NULL); + FREE(rb_surface); +} + + +struct pipe_sampler_view * +rbug_sampler_view_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, + struct pipe_sampler_view *view) +{ + struct rbug_sampler_view *rb_view; + + if (!view) + goto error; + + assert(view->texture == rb_resource->resource); + + rb_view = MALLOC(sizeof(struct rbug_sampler_view)); + + rb_view->base = *view; + rb_view->base.reference.count = 1; + rb_view->base.texture = NULL; + pipe_resource_reference(&rb_view->base.texture, &rb_resource->base); + rb_view->base.context = rb_context->pipe; + rb_view->sampler_view = view; + + return &rb_view->base; +error: + return NULL; +} + +void +rbug_sampler_view_destroy(struct rbug_context *rb_context, + struct rbug_sampler_view *rb_view) +{ + pipe_resource_reference(&rb_view->base.texture, NULL); + rb_context->pipe->sampler_view_destroy(rb_context->pipe, + rb_view->sampler_view); + FREE(rb_view); +} + + +struct pipe_transfer * +rbug_transfer_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, + struct pipe_transfer *transfer) +{ + struct rbug_transfer *rb_transfer; + + if(!transfer) + goto error; + + assert(transfer->resource == rb_resource->resource); + + rb_transfer = CALLOC_STRUCT(rbug_transfer); + if(!rb_transfer) + goto error; + + memcpy(&rb_transfer->base, transfer, sizeof(struct pipe_transfer)); + + rb_transfer->base.resource = NULL; + rb_transfer->transfer = transfer; + rb_transfer->pipe = rb_context->pipe; + + pipe_resource_reference(&rb_transfer->base.resource, &rb_resource->base); + assert(rb_transfer->base.resource == &rb_resource->base); + + return &rb_transfer->base; + +error: + rb_context->pipe->transfer_destroy(rb_context->pipe, transfer); + return NULL; +} + +void +rbug_transfer_destroy(struct rbug_context *rb_context, + struct rbug_transfer *rb_transfer) +{ + pipe_resource_reference(&rb_transfer->base.resource, NULL); + rb_transfer->pipe->transfer_destroy(rb_context->pipe, + rb_transfer->transfer); + FREE(rb_transfer); +} + +void * +rbug_shader_create(struct rbug_context *rb_context, + const struct pipe_shader_state *state, + void *result, enum rbug_shader_type type) +{ + struct rbug_shader *rb_shader = CALLOC_STRUCT(rbug_shader); + + rb_shader->type = type; + rb_shader->shader = result; + rb_shader->tokens = tgsi_dup_tokens(state->tokens); + + /* works on context as well since its just a macro */ + rbug_screen_add_to_list(rb_context, shaders, rb_shader); + + return rb_shader; +} + +void +rbug_shader_destroy(struct rbug_context *rb_context, + struct rbug_shader *rb_shader) +{ + struct pipe_context *pipe = rb_context->pipe; + + /* works on context as well since its just a macro */ + rbug_screen_remove_from_list(rb_context, shaders, rb_shader); + + switch(rb_shader->type) { + case RBUG_SHADER_FRAGMENT: + if (rb_shader->replaced_shader) + pipe->delete_fs_state(pipe, rb_shader->replaced_shader); + pipe->delete_fs_state(pipe, rb_shader->shader); + break; + case RBUG_SHADER_VERTEX: + if (rb_shader->replaced_shader) + pipe->delete_vs_state(pipe, rb_shader->replaced_shader); + pipe->delete_vs_state(pipe, rb_shader->shader); + break; + case RBUG_SHADER_GEOM: + if (rb_shader->replaced_shader) + pipe->delete_gs_state(pipe, rb_shader->replaced_shader); + pipe->delete_gs_state(pipe, rb_shader->shader); + break; + default: + assert(0); + } + + FREE(rb_shader->replaced_tokens); + FREE(rb_shader->tokens); + FREE(rb_shader); +} diff --git a/src/gallium/drivers/rbug/rbug_objects.h b/src/gallium/drivers/rbug/rbug_objects.h new file mode 100644 index 00000000000..49c128d3d1a --- /dev/null +++ b/src/gallium/drivers/rbug/rbug_objects.h @@ -0,0 +1,226 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * 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 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 VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef RBUG_OBJECTS_H +#define RBUG_OBJECTS_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + +#include "rbug_screen.h" + +struct rbug_context; + + +struct rbug_resource +{ + struct pipe_resource base; + + struct pipe_resource *resource; + + struct rbug_list list; +}; + + +enum rbug_shader_type +{ + RBUG_SHADER_GEOM, + RBUG_SHADER_VERTEX, + RBUG_SHADER_FRAGMENT, +}; + +struct rbug_shader +{ + struct rbug_list list; + + void *shader; + void *tokens; + void *replaced_shader; + void *replaced_tokens; + + enum rbug_shader_type type; + boolean disabled; +}; + + +struct rbug_sampler_view +{ + struct pipe_sampler_view base; + + struct pipe_sampler_view *sampler_view; +}; + + +struct rbug_surface +{ + struct pipe_surface base; + + struct pipe_surface *surface; +}; + + +struct rbug_transfer +{ + struct pipe_transfer base; + + struct pipe_context *pipe; + struct pipe_transfer *transfer; +}; + + +static INLINE struct rbug_resource * +rbug_resource(struct pipe_resource *_resource) +{ + if (!_resource) + return NULL; + (void)rbug_screen(_resource->screen); + return (struct rbug_resource *)_resource; +} + +static INLINE struct rbug_sampler_view * +rbug_sampler_view(struct pipe_sampler_view *_sampler_view) +{ + if (!_sampler_view) + return NULL; + (void)rbug_resource(_sampler_view->texture); + return (struct rbug_sampler_view *)_sampler_view; +} + +static INLINE struct rbug_surface * +rbug_surface(struct pipe_surface *_surface) +{ + if (!_surface) + return NULL; + (void)rbug_resource(_surface->texture); + return (struct rbug_surface *)_surface; +} + +static INLINE struct rbug_transfer * +rbug_transfer(struct pipe_transfer *_transfer) +{ + if (!_transfer) + return NULL; + (void)rbug_resource(_transfer->resource); + return (struct rbug_transfer *)_transfer; +} + +static INLINE struct rbug_shader * +rbug_shader(void *_state) +{ + if (!_state) + return NULL; + return (struct rbug_shader *)_state; +} + +static INLINE struct pipe_resource * +rbug_resource_unwrap(struct pipe_resource *_resource) +{ + if (!_resource) + return NULL; + return rbug_resource(_resource)->resource; +} + +static INLINE struct pipe_sampler_view * +rbug_sampler_view_unwrap(struct pipe_sampler_view *_sampler_view) +{ + if (!_sampler_view) + return NULL; + return rbug_sampler_view(_sampler_view)->sampler_view; +} + +static INLINE struct pipe_surface * +rbug_surface_unwrap(struct pipe_surface *_surface) +{ + if (!_surface) + return NULL; + return rbug_surface(_surface)->surface; +} + +static INLINE struct pipe_transfer * +rbug_transfer_unwrap(struct pipe_transfer *_transfer) +{ + if (!_transfer) + return NULL; + return rbug_transfer(_transfer)->transfer; +} + +static INLINE void * +rbug_shader_unwrap(void *_state) +{ + struct rbug_shader *shader; + if (!_state) + return NULL; + + shader = rbug_shader(_state); + return shader->replaced_shader ? shader->replaced_shader : shader->shader; +} + + +struct pipe_resource * +rbug_resource_create(struct rbug_screen *rb_screen, + struct pipe_resource *resource); + +void +rbug_resource_destroy(struct rbug_resource *rb_resource); + +struct pipe_surface * +rbug_surface_create(struct rbug_resource *rb_resource, + struct pipe_surface *surface); + +void +rbug_surface_destroy(struct rbug_surface *rb_surface); + +struct pipe_sampler_view * +rbug_sampler_view_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, + struct pipe_sampler_view *view); + +void +rbug_sampler_view_destroy(struct rbug_context *rb_context, + struct rbug_sampler_view *rb_sampler_view); + +struct pipe_transfer * +rbug_transfer_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, + struct pipe_transfer *transfer); + +void +rbug_transfer_destroy(struct rbug_context *rb_context, + struct rbug_transfer *rb_transfer); + +void * +rbug_shader_create(struct rbug_context *rb_context, + const struct pipe_shader_state *state, + void *result, enum rbug_shader_type type); + +void +rbug_shader_destroy(struct rbug_context *rb_context, + struct rbug_shader *rb_shader); + + +#endif /* RBUG_OBJECTS_H */ diff --git a/src/gallium/drivers/rbug/rbug_public.h b/src/gallium/drivers/rbug/rbug_public.h new file mode 100644 index 00000000000..b66740b49cd --- /dev/null +++ b/src/gallium/drivers/rbug/rbug_public.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * 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 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 VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef RBUG_PUBLIC_H +#define RBUG_PUBLIC_H + +struct pipe_screen; +struct pipe_context; + +struct pipe_screen * +rbug_screen_create(struct pipe_screen *screen); + +boolean +rbug_enabled(void); + +#endif /* RBUG_PUBLIC_H */ diff --git a/src/gallium/drivers/rbug/rbug_screen.c b/src/gallium/drivers/rbug/rbug_screen.c new file mode 100644 index 00000000000..2b60af2302a --- /dev/null +++ b/src/gallium/drivers/rbug/rbug_screen.c @@ -0,0 +1,351 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * 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 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 VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "pipe/p_screen.h" +#include "pipe/p_state.h" +#include "util/u_memory.h" +#include "util/u_debug.h" +#include "util/u_simple_list.h" + +#include "rbug_public.h" +#include "rbug_screen.h" +#include "rbug_context.h" +#include "rbug_objects.h" + +DEBUG_GET_ONCE_BOOL_OPTION(rbug, "GALLIUM_RBUG", FALSE) + +static void +rbug_screen_destroy(struct pipe_screen *_screen) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + screen->destroy(screen); + + FREE(rb_screen); +} + +static const char * +rbug_screen_get_name(struct pipe_screen *_screen) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->get_name(screen); +} + +static const char * +rbug_screen_get_vendor(struct pipe_screen *_screen) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->get_vendor(screen); +} + +static int +rbug_screen_get_param(struct pipe_screen *_screen, + enum pipe_cap param) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->get_param(screen, + param); +} + +static float +rbug_screen_get_paramf(struct pipe_screen *_screen, + enum pipe_cap param) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->get_paramf(screen, + param); +} + +static boolean +rbug_screen_is_format_supported(struct pipe_screen *_screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned tex_usage, + unsigned geom_flags) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->is_format_supported(screen, + format, + target, + tex_usage, + geom_flags); +} + +static struct pipe_context * +rbug_screen_context_create(struct pipe_screen *_screen, + void *priv) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_context *result; + + result = screen->context_create(screen, priv); + if (result) + return rbug_context_create(_screen, result); + return NULL; +} + +static struct pipe_resource * +rbug_screen_resource_create(struct pipe_screen *_screen, + const struct pipe_resource *templat) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *result; + + result = screen->resource_create(screen, + templat); + + if (result) + return rbug_resource_create(rb_screen, result); + return NULL; +} + +static struct pipe_resource * +rbug_screen_resource_from_handle(struct pipe_screen *_screen, + const struct pipe_resource *templ, + struct winsys_handle *handle) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *result; + + result = screen->resource_from_handle(screen, templ, handle); + + result = rbug_resource_create(rbug_screen(_screen), result); + + return result; +} + +static boolean +rbug_screen_resource_get_handle(struct pipe_screen *_screen, + struct pipe_resource *_resource, + struct winsys_handle *handle) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *resource = rb_resource->resource; + + return screen->resource_get_handle(screen, resource, handle); +} + + + +static void +rbug_screen_resource_destroy(struct pipe_screen *screen, + struct pipe_resource *_resource) +{ + rbug_resource_destroy(rbug_resource(_resource)); +} + +static struct pipe_surface * +rbug_screen_get_tex_surface(struct pipe_screen *_screen, + struct pipe_resource *_resource, + unsigned face, + unsigned level, + unsigned zslice, + unsigned usage) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *resource = rb_resource->resource; + struct pipe_surface *result; + + result = screen->get_tex_surface(screen, + resource, + face, + level, + zslice, + usage); + + if (result) + return rbug_surface_create(rb_resource, result); + return NULL; +} + +static void +rbug_screen_tex_surface_destroy(struct pipe_surface *_surface) +{ + rbug_surface_destroy(rbug_surface(_surface)); +} + + + +static struct pipe_resource * +rbug_screen_user_buffer_create(struct pipe_screen *_screen, + void *ptr, + unsigned bytes, + unsigned usage) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *result; + + result = screen->user_buffer_create(screen, + ptr, + bytes, + usage); + + if (result) + return rbug_resource_create(rb_screen, result); + return NULL; +} + + + +static void +rbug_screen_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_surface *_surface, + void *context_private) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct rbug_surface *rb_surface = rbug_surface(_surface); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_surface *surface = rb_surface->surface; + + screen->flush_frontbuffer(screen, + surface, + context_private); +} + +static void +rbug_screen_fence_reference(struct pipe_screen *_screen, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + screen->fence_reference(screen, + ptr, + fence); +} + +static int +rbug_screen_fence_signalled(struct pipe_screen *_screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->fence_signalled(screen, + fence, + flags); +} + +static int +rbug_screen_fence_finish(struct pipe_screen *_screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->fence_finish(screen, + fence, + flags); +} + +boolean +rbug_enabled() +{ + return debug_get_option_rbug(); +} + +struct pipe_screen * +rbug_screen_create(struct pipe_screen *screen) +{ + struct rbug_screen *rb_screen; + + if (!debug_get_option_rbug()) + return screen; + + rb_screen = CALLOC_STRUCT(rbug_screen); + if (!rb_screen) + return screen; + + pipe_mutex_init(rb_screen->list_mutex); + make_empty_list(&rb_screen->contexts); + make_empty_list(&rb_screen->resources); + make_empty_list(&rb_screen->surfaces); + make_empty_list(&rb_screen->transfers); + + rb_screen->base.winsys = NULL; + + rb_screen->base.destroy = rbug_screen_destroy; + rb_screen->base.get_name = rbug_screen_get_name; + rb_screen->base.get_vendor = rbug_screen_get_vendor; + rb_screen->base.get_param = rbug_screen_get_param; + rb_screen->base.get_paramf = rbug_screen_get_paramf; + rb_screen->base.is_format_supported = rbug_screen_is_format_supported; + rb_screen->base.context_create = rbug_screen_context_create; + rb_screen->base.resource_create = rbug_screen_resource_create; + rb_screen->base.resource_from_handle = rbug_screen_resource_from_handle; + rb_screen->base.resource_get_handle = rbug_screen_resource_get_handle; + rb_screen->base.resource_destroy = rbug_screen_resource_destroy; + rb_screen->base.get_tex_surface = rbug_screen_get_tex_surface; + rb_screen->base.tex_surface_destroy = rbug_screen_tex_surface_destroy; + rb_screen->base.user_buffer_create = rbug_screen_user_buffer_create; + rb_screen->base.flush_frontbuffer = rbug_screen_flush_frontbuffer; + rb_screen->base.fence_reference = rbug_screen_fence_reference; + rb_screen->base.fence_signalled = rbug_screen_fence_signalled; + rb_screen->base.fence_finish = rbug_screen_fence_finish; + + rb_screen->screen = screen; + + rb_screen->private_context = screen->context_create(screen, NULL); + if (!rb_screen->private_context) + goto err_free; + + rb_screen->rbug = rbug_start(rb_screen); + + if (!rb_screen->rbug) + goto err_context; + + return &rb_screen->base; + +err_context: + rb_screen->private_context->destroy(rb_screen->private_context); +err_free: + FREE(rb_screen); + return screen; +} diff --git a/src/gallium/drivers/rbug/rbug_screen.h b/src/gallium/drivers/rbug/rbug_screen.h new file mode 100644 index 00000000000..a53afac05e9 --- /dev/null +++ b/src/gallium/drivers/rbug/rbug_screen.h @@ -0,0 +1,100 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * 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 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 VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef RBUG_SCREEN_H +#define RBUG_SCREEN_H + +#include "pipe/p_screen.h" +#include "pipe/p_defines.h" + +#include "os/os_thread.h" + +struct rbug_list { + struct rbug_list *next; + struct rbug_list *prev; +}; + + +struct rbug_screen +{ + struct pipe_screen base; + + struct pipe_screen *screen; + struct pipe_context *private_context; + + /* remote debugger */ + struct rbug_rbug *rbug; + + pipe_mutex list_mutex; + int num_contexts; + int num_resources; + int num_surfaces; + int num_transfers; + struct rbug_list contexts; + struct rbug_list resources; + struct rbug_list surfaces; + struct rbug_list transfers; +}; + +static INLINE struct rbug_screen * +rbug_screen(struct pipe_screen *screen) +{ + return (struct rbug_screen *)screen; +} + +#define rbug_screen_add_to_list(scr, name, obj) \ + do { \ + pipe_mutex_lock(scr->list_mutex); \ + insert_at_head(&scr->name, &obj->list); \ + scr->num_##name++; \ + pipe_mutex_unlock(scr->list_mutex); \ + } while (0) + +#define rbug_screen_remove_from_list(scr, name, obj) \ + do { \ + pipe_mutex_lock(scr->list_mutex); \ + remove_from_list(&obj->list); \ + scr->num_##name--; \ + pipe_mutex_unlock(scr->list_mutex); \ + } while (0) + + + +/********************************************************** + * rbug_core.c + */ + +struct rbug_rbug; + +struct rbug_rbug * +rbug_start(struct rbug_screen *rb_screen); + +void +rbug_stop(struct rbug_rbug *rbug); + + +#endif /* RBUG_SCREEN_H */ diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index 0f1bcc21bd6..2f10b46e989 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -36,6 +36,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_inlines.h" +#include "tgsi/tgsi_exec.h" #include "sp_clear.h" #include "sp_context.h" #include "sp_flush.h" @@ -123,6 +124,8 @@ softpipe_destroy( struct pipe_context *pipe ) } } + tgsi_exec_machine_destroy(softpipe->fs_machine); + FREE( softpipe ); } @@ -294,6 +297,8 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->vertex_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe ); } + softpipe->fs_machine = tgsi_exec_machine_create(); + /* setup quad rendering stages */ softpipe->quad.shade = sp_quad_shade_stage(softpipe); softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe); diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 92607874b60..b3d3fe620fd 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -109,6 +109,9 @@ struct softpipe_context { /** The reduced version of the primitive supplied by the state tracker */ unsigned reduced_api_prim; + /** Derived information about which winding orders to cull */ + unsigned cull_mode; + /** * The reduced primitive after unfilled triangles, wide-line decomposition, * etc, are taken into account. This is the primitive type that's actually @@ -140,6 +143,8 @@ struct softpipe_context { struct sp_sampler_varient *frag_samplers_list[PIPE_MAX_SAMPLERS]; } tgsi; + struct tgsi_exec_machine *fs_machine; + /** The primitive drawing context */ struct draw_context *draw; diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index a58bc107c0a..db0d1755103 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -158,26 +158,27 @@ static INLINE cptrf4 get_vert( const void *vertex_buffer, * draw elements / indexed primitives */ static void -sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) +sp_vbuf_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr) { struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); struct softpipe_context *softpipe = cvbr->softpipe; const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float); const void *vertex_buffer = cvbr->vertex_buffer; - struct setup_context *setup_ctx = cvbr->setup; + struct setup_context *setup = cvbr->setup; + const boolean flatshade_first = softpipe->rasterizer->flatshade_first; unsigned i; switch (cvbr->prim) { case PIPE_PRIM_POINTS: for (i = 0; i < nr; i++) { - sp_setup_point( setup_ctx, + sp_setup_point( setup, get_vert(vertex_buffer, indices[i-0], stride) ); } break; case PIPE_PRIM_LINES: for (i = 1; i < nr; i += 2) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); } @@ -185,7 +186,7 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) case PIPE_PRIM_LINE_STRIP: for (i = 1; i < nr; i ++) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); } @@ -193,48 +194,41 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) case PIPE_PRIM_LINE_LOOP: for (i = 1; i < nr; i ++) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); } if (nr) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, indices[nr-1], stride), get_vert(vertex_buffer, indices[0], stride) ); } break; case PIPE_PRIM_TRIANGLES: - if (softpipe->rasterizer->flatshade_first) { - for (i = 2; i < nr; i += 3) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-2], stride) ); - } - } - else { - for (i = 2; i < nr; i += 3) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - } + for (i = 2; i < nr; i += 3) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); } break; case PIPE_PRIM_TRIANGLE_STRIP: - if (softpipe->rasterizer->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit first triangle vertex as first triangle vertex */ + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-2], stride), get_vert(vertex_buffer, indices[i+(i&1)-1], stride), - get_vert(vertex_buffer, indices[i-(i&1)], stride), - get_vert(vertex_buffer, indices[i-2], stride) ); + get_vert(vertex_buffer, indices[i-(i&1)], stride) ); + } } else { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit last triangle vertex as last triangle vertex */ + sp_setup_tri( setup, get_vert(vertex_buffer, indices[i+(i&1)-2], stride), get_vert(vertex_buffer, indices[i-(i&1)-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); @@ -243,17 +237,19 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_TRIANGLE_FAN: - if (softpipe->rasterizer->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit first non-spoke vertex as first vertex */ + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[0], stride), - get_vert(vertex_buffer, indices[i-1], stride) ); + get_vert(vertex_buffer, indices[0], stride) ); } } else { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit last non-spoke vertex as last vertex */ + sp_setup_tri( setup, get_vert(vertex_buffer, indices[0], stride), get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); @@ -262,43 +258,88 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_QUADS: - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); + /* GL quads don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_QUAD_STRIP: - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); + /* GL quad strips don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_POLYGON: /* Almost same as tri fan but the _first_ vertex specifies the flat - * shading color. Note that the first polygon vertex is passed as - * the last triangle vertex here. - * flatshade_first state makes no difference. + * shading color. */ - for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[0], stride) ); + if (flatshade_first) { + /* emit first polygon vertex as first triangle vertex */ + for (i = 2; i < nr; i += 1) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[0], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } + } + else { + /* emit first polygon vertex as last triangle vertex */ + for (i = 2; i < nr; i += 1) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[0], stride) ); + } } break; @@ -317,23 +358,24 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) { struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); struct softpipe_context *softpipe = cvbr->softpipe; - struct setup_context *setup_ctx = cvbr->setup; + struct setup_context *setup = cvbr->setup; const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float); const void *vertex_buffer = (void *) get_vert(cvbr->vertex_buffer, start, stride); + const boolean flatshade_first = softpipe->rasterizer->flatshade_first; unsigned i; switch (cvbr->prim) { case PIPE_PRIM_POINTS: for (i = 0; i < nr; i++) { - sp_setup_point( setup_ctx, + sp_setup_point( setup, get_vert(vertex_buffer, i-0, stride) ); } break; case PIPE_PRIM_LINES: for (i = 1; i < nr; i += 2) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride) ); } @@ -341,7 +383,7 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) case PIPE_PRIM_LINE_STRIP: for (i = 1; i < nr; i ++) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride) ); } @@ -349,48 +391,40 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) case PIPE_PRIM_LINE_LOOP: for (i = 1; i < nr; i ++) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride) ); } if (nr) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, nr-1, stride), get_vert(vertex_buffer, 0, stride) ); } break; case PIPE_PRIM_TRIANGLES: - if (softpipe->rasterizer->flatshade_first) { - for (i = 2; i < nr; i += 3) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-2, stride) ); - } - } - else { - for (i = 2; i < nr; i += 3) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); - } + for (i = 2; i < nr; i += 3) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); } break; case PIPE_PRIM_TRIANGLE_STRIP: - if (softpipe->rasterizer->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i++) { - sp_setup_tri( setup_ctx, + /* emit first triangle vertex as first triangle vertex */ + sp_setup_tri( setup, + get_vert(vertex_buffer, i-2, stride), get_vert(vertex_buffer, i+(i&1)-1, stride), - get_vert(vertex_buffer, i-(i&1), stride), - get_vert(vertex_buffer, i-2, stride) ); + get_vert(vertex_buffer, i-(i&1), stride) ); } } else { for (i = 2; i < nr; i++) { - sp_setup_tri( setup_ctx, + /* emit last triangle vertex as last triangle vertex */ + sp_setup_tri( setup, get_vert(vertex_buffer, i+(i&1)-2, stride), get_vert(vertex_buffer, i-(i&1)-1, stride), get_vert(vertex_buffer, i-0, stride) ); @@ -399,17 +433,19 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_TRIANGLE_FAN: - if (softpipe->rasterizer->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit first non-spoke vertex as first vertex */ + sp_setup_tri( setup, + get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, 0, stride), - get_vert(vertex_buffer, i-1, stride) ); + get_vert(vertex_buffer, 0, stride) ); } } else { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit last non-spoke vertex as last vertex */ + sp_setup_tri( setup, get_vert(vertex_buffer, 0, stride), get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride) ); @@ -418,42 +454,86 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_QUADS: - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); + /* GL quads don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; case PIPE_PRIM_QUAD_STRIP: - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-0, stride) ); + /* GL quad strips don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; case PIPE_PRIM_POLYGON: /* Almost same as tri fan but the _first_ vertex specifies the flat - * shading color. Note that the first polygon vertex is passed as - * the last triangle vertex here. - * flatshade_first state makes no difference. + * shading color. */ - for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, 0, stride) ); + if (flatshade_first) { + /* emit first polygon vertex as first triangle vertex */ + for (i = 2; i < nr; i += 1) { + sp_setup_tri( setup, + get_vert(vertex_buffer, 0, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } + } + else { + /* emit first polygon vertex as last triangle vertex */ + for (i = 2; i < nr; i += 1) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, 0, stride) ); + } } break; @@ -492,7 +572,7 @@ sp_create_vbuf_backend(struct softpipe_context *sp) cvbr->base.map_vertices = sp_vbuf_map_vertices; cvbr->base.unmap_vertices = sp_vbuf_unmap_vertices; cvbr->base.set_primitive = sp_vbuf_set_primitive; - cvbr->base.draw = sp_vbuf_draw; + cvbr->base.draw_elements = sp_vbuf_draw_elements; cvbr->base.draw_arrays = sp_vbuf_draw_arrays; cvbr->base.release_vertices = sp_vbuf_release_vertices; cvbr->base.destroy = sp_vbuf_destroy; diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c index 8ae5a7f028b..907e94b59b9 100644 --- a/src/gallium/drivers/softpipe/sp_quad_fs.c +++ b/src/gallium/drivers/softpipe/sp_quad_fs.c @@ -50,8 +50,8 @@ struct quad_shade_stage { struct quad_stage stage; /**< base class */ - struct tgsi_exec_machine *machine; - struct tgsi_exec_vector *inputs, *outputs; + + /* no other fields at this time */ }; @@ -70,9 +70,8 @@ quad_shade_stage(struct quad_stage *qs) static INLINE boolean shade_quad(struct quad_stage *qs, struct quad_header *quad) { - struct quad_shade_stage *qss = quad_shade_stage( qs ); struct softpipe_context *softpipe = qs->softpipe; - struct tgsi_exec_machine *machine = qss->machine; + struct tgsi_exec_machine *machine = softpipe->fs_machine; /* run shader */ return softpipe->fs->run( softpipe->fs, machine, quad ); @@ -108,9 +107,8 @@ shade_quads(struct quad_stage *qs, struct quad_header *quads[], unsigned nr) { - struct quad_shade_stage *qss = quad_shade_stage( qs ); struct softpipe_context *softpipe = qs->softpipe; - struct tgsi_exec_machine *machine = qss->machine; + struct tgsi_exec_machine *machine = softpipe->fs_machine; unsigned i, pass = 0; for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { @@ -139,11 +137,10 @@ shade_quads(struct quad_stage *qs, static void shade_begin(struct quad_stage *qs) { - struct quad_shade_stage *qss = quad_shade_stage(qs); struct softpipe_context *softpipe = qs->softpipe; softpipe->fs->prepare( softpipe->fs, - qss->machine, + softpipe->fs_machine, (struct tgsi_sampler **) softpipe->tgsi.frag_samplers_list ); @@ -154,10 +151,6 @@ shade_begin(struct quad_stage *qs) static void shade_destroy(struct quad_stage *qs) { - struct quad_shade_stage *qss = (struct quad_shade_stage *) qs; - - tgsi_exec_machine_destroy(qss->machine); - FREE( qs ); } @@ -174,16 +167,9 @@ sp_quad_shade_stage( struct softpipe_context *softpipe ) qss->stage.run = shade_quads; qss->stage.destroy = shade_destroy; - qss->machine = tgsi_exec_machine_create(); - if (!qss->machine) - goto fail; - return &qss->stage; fail: - if (qss && qss->machine) - tgsi_exec_machine_destroy(qss->machine); - FREE(qss); return NULL; } diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c index 4ef5d9f7b1d..b959af63aff 100644 --- a/src/gallium/drivers/softpipe/sp_query.c +++ b/src/gallium/drivers/softpipe/sp_query.c @@ -30,6 +30,7 @@ */ #include "draw/draw_context.h" +#include "os/os_time.h" #include "pipe/p_defines.h" #include "util/u_memory.h" #include "sp_context.h" @@ -37,6 +38,7 @@ #include "sp_state.h" struct softpipe_query { + unsigned type; uint64_t start; uint64_t end; }; @@ -51,8 +53,13 @@ static struct pipe_query * softpipe_create_query(struct pipe_context *pipe, unsigned type) { - assert(type == PIPE_QUERY_OCCLUSION_COUNTER); - return (struct pipe_query *)CALLOC_STRUCT( softpipe_query ); + struct softpipe_query* sq; + + assert(type == PIPE_QUERY_OCCLUSION_COUNTER || type == PIPE_QUERY_TIME_ELAPSED); + sq = CALLOC_STRUCT( softpipe_query ); + sq->type = type; + + return (struct pipe_query *)sq; } @@ -69,7 +76,17 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) struct softpipe_context *softpipe = softpipe_context( pipe ); struct softpipe_query *sq = softpipe_query(q); - sq->start = softpipe->occlusion_count; + switch (sq->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + sq->start = softpipe->occlusion_count; + break; + case PIPE_QUERY_TIME_ELAPSED: + sq->start = 1000*os_time_get(); + break; + default: + assert(0); + break; + } softpipe->active_query_count++; softpipe->dirty |= SP_NEW_QUERY; } @@ -82,7 +99,17 @@ softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) struct softpipe_query *sq = softpipe_query(q); softpipe->active_query_count--; - sq->end = softpipe->occlusion_count; + switch (sq->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + sq->end = softpipe->occlusion_count; + break; + case PIPE_QUERY_TIME_ELAPSED: + sq->end = 1000*os_time_get(); + break; + default: + assert(0); + break; + } softpipe->dirty |= SP_NEW_QUERY; } diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index ad59ee90936..73987c913e5 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -33,6 +33,7 @@ #include "pipe/p_screen.h" #include "state_tracker/sw_winsys.h" +#include "tgsi/tgsi_exec.h" #include "sp_texture.h" #include "sp_screen.h" @@ -56,7 +57,7 @@ softpipe_get_name(struct pipe_screen *screen) static int -softpipe_get_param(struct pipe_screen *screen, int param) +softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: @@ -81,6 +82,8 @@ softpipe_get_param(struct pipe_screen *screen, int param) return PIPE_MAX_COLOR_BUFS; case PIPE_CAP_OCCLUSION_QUERY: return 1; + case PIPE_CAP_TIMER_QUERY: + return 1; case PIPE_CAP_TEXTURE_MIRROR_CLAMP: return 1; case PIPE_CAP_TEXTURE_MIRROR_REPEAT: @@ -110,6 +113,36 @@ softpipe_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 1; + + case PIPE_CAP_MAX_VS_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_ALU_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_ALU_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_TEX_INDIRECTIONS: + case PIPE_CAP_MAX_FS_TEX_INDIRECTIONS: + /* There is no limit in number of instructions beyond available memory */ + return 32768; + case PIPE_CAP_MAX_VS_CONTROL_FLOW_DEPTH: + case PIPE_CAP_MAX_FS_CONTROL_FLOW_DEPTH: + return TGSI_EXEC_MAX_NESTING; + case PIPE_CAP_MAX_VS_INPUTS: + case PIPE_CAP_MAX_FS_INPUTS: + return TGSI_EXEC_MAX_INPUT_ATTRIBS; + case PIPE_CAP_MAX_FS_CONSTS: + case PIPE_CAP_MAX_VS_CONSTS: + return TGSI_EXEC_MAX_CONST_BUFFER; + case PIPE_CAP_MAX_VS_TEMPS: + case PIPE_CAP_MAX_FS_TEMPS: + return TGSI_EXEC_NUM_TEMPS; + case PIPE_CAP_MAX_VS_ADDRS: + case PIPE_CAP_MAX_FS_ADDRS: + return TGSI_EXEC_NUM_ADDRS; + case PIPE_CAP_MAX_VS_PREDS: + case PIPE_CAP_MAX_FS_PREDS: + return TGSI_EXEC_NUM_PREDS; + default: return 0; } @@ -117,7 +150,7 @@ softpipe_get_param(struct pipe_screen *screen, int param) static float -softpipe_get_paramf(struct pipe_screen *screen, int param) +softpipe_get_paramf(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c index 86354664e4b..5d727dc00df 100644 --- a/src/gallium/drivers/softpipe/sp_setup.c +++ b/src/gallium/drivers/softpipe/sp_setup.c @@ -111,34 +111,13 @@ struct setup_context { uint numFragsWritten; /**< per primitive */ #endif - unsigned winding; /* which winding to cull */ + unsigned cull_face; /* which faces cull */ unsigned nr_vertex_attrs; }; -/** - * Do triangle cull test using tri determinant (sign indicates orientation) - * \return true if triangle is to be culled. - */ -static INLINE boolean -cull_tri(const struct setup_context *setup, float det) -{ - if (det != 0) { - /* if (det < 0 then Z points toward camera and triangle is - * counter-clockwise winding. - */ - unsigned winding = (det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW; - - if ((winding & setup->winding) == 0) - return FALSE; - } - - /* Culled: - */ - return TRUE; -} @@ -304,7 +283,10 @@ setup_sort_vertices(struct setup_context *setup, const float (*v1)[4], const float (*v2)[4]) { - setup->vprovoke = v2; + if (setup->softpipe->rasterizer->flatshade_first) + setup->vprovoke = v0; + else + setup->vprovoke = v2; /* determine bottom to top order of vertices */ { @@ -390,8 +372,16 @@ setup_sort_vertices(struct setup_context *setup, * 0 = front-facing, 1 = back-facing */ setup->facing = - ((det > 0.0) ^ - (setup->softpipe->rasterizer->front_winding == PIPE_WINDING_CW)); + ((det < 0.0) ^ + (setup->softpipe->rasterizer->front_ccw)); + + { + unsigned face = setup->facing == 0 ? PIPE_FACE_FRONT : PIPE_FACE_BACK; + + if (face & setup->cull_face) + return FALSE; + } + /* Prepare pixel offset for rasterisation: * - pixel center (0.5, 0.5) for GL, or @@ -829,11 +819,9 @@ sp_setup_tri(struct setup_context *setup, setup->numFragsWritten = 0; #endif - if (cull_tri( setup, det )) - return; - if (!setup_sort_vertices( setup, det, v0, v1, v2 )) return; + setup_tri_coefficients( setup ); setup_tri_edges( setup ); @@ -1417,14 +1405,14 @@ sp_setup_prepare(struct setup_context *setup) sp->quad.first->begin( sp->quad.first ); if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES && - sp->rasterizer->fill_cw == PIPE_POLYGON_MODE_FILL && - sp->rasterizer->fill_ccw == PIPE_POLYGON_MODE_FILL) { + sp->rasterizer->fill_front == PIPE_POLYGON_MODE_FILL && + sp->rasterizer->fill_back == PIPE_POLYGON_MODE_FILL) { /* we'll do culling */ - setup->winding = sp->rasterizer->cull_mode; + setup->cull_face = sp->rasterizer->cull_face; } else { /* 'draw' will do culling */ - setup->winding = PIPE_WINDING_NONE; + setup->cull_face = PIPE_FACE_NONE; } } diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c index 7f072f5a269..816e0c18bd2 100644 --- a/src/gallium/drivers/softpipe/sp_state_fs.c +++ b/src/gallium/drivers/softpipe/sp_state_fs.c @@ -36,6 +36,7 @@ #include "draw/draw_context.h" #include "draw/draw_vs.h" #include "tgsi/tgsi_dump.h" +#include "tgsi/tgsi_exec.h" #include "tgsi/tgsi_scan.h" #include "tgsi/tgsi_parse.h" @@ -95,10 +96,18 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs) void softpipe_delete_fs_state(struct pipe_context *pipe, void *fs) { + struct softpipe_context *softpipe = softpipe_context(pipe); struct sp_fragment_shader *state = fs; assert(fs != softpipe_context(pipe)->fs); - + + if (softpipe->fs_machine->Tokens == state->shader.tokens) { + /* unbind the shader from the tgsi executor if we're + * deleting it. + */ + tgsi_exec_machine_bind_shader(softpipe->fs_machine, NULL, 0, NULL); + } + state->delete( state ); } diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 7aa85559b23..4e6123fbd07 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -343,11 +343,15 @@ softpipe_get_transfer(struct pipe_context *pipe, if (spt) { struct pipe_transfer *pt = &spt->base; enum pipe_format format = resource->format; + const unsigned hgt = u_minify(spr->base.height0, sr.level); + const unsigned nblocksy = util_format_get_nblocksy(format, hgt); + pipe_resource_reference(&pt->resource, resource); pt->sr = sr; pt->usage = usage; pt->box = *box; pt->stride = spr->stride[sr.level]; + pt->slice_stride = pt->stride * nblocksy; spt->offset = sp_get_tex_image_offset(spr, sr.level, sr.face, box->z); diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c index 5253c45cb20..660eb0757a6 100644 --- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c +++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c @@ -36,16 +36,17 @@ /* Hardware frontwinding is always set up as SVGA3D_FRONTWINDING_CW. */ static SVGA3dFace svga_translate_cullmode( unsigned mode, - unsigned front_winding ) + unsigned front_ccw ) { + const int hw_front_ccw = 0; /* hardware is always CW */ switch (mode) { - case PIPE_WINDING_NONE: + case PIPE_FACE_NONE: return SVGA3D_FACE_NONE; - case PIPE_WINDING_CCW: - return SVGA3D_FACE_BACK; - case PIPE_WINDING_CW: - return SVGA3D_FACE_FRONT; - case PIPE_WINDING_BOTH: + case PIPE_FACE_FRONT: + return front_ccw == hw_front_ccw ? SVGA3D_FACE_FRONT : SVGA3D_FACE_BACK; + case PIPE_FACE_BACK: + return front_ccw == hw_front_ccw ? SVGA3D_FACE_BACK : SVGA3D_FACE_FRONT; + case PIPE_FACE_FRONT_AND_BACK: return SVGA3D_FACE_FRONT_BACK; default: assert(0); @@ -81,8 +82,8 @@ svga_create_rasterizer_state(struct pipe_context *pipe, /* fill_cw, fill_ccw - draw module or index translation */ rast->shademode = svga_translate_flatshade( templ->flatshade ); - rast->cullmode = svga_translate_cullmode( templ->cull_mode, - templ->front_winding ); + rast->cullmode = svga_translate_cullmode( templ->cull_face, + templ->front_ccw ); rast->scissortestenable = templ->scissor; rast->multisampleantialias = templ->multisample; rast->antialiasedlineenable = templ->line_smooth; @@ -117,31 +118,31 @@ svga_create_rasterizer_state(struct pipe_context *pipe, rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS; { - boolean offset_cw = templ->offset_cw; - boolean offset_ccw = templ->offset_ccw; - boolean offset = 0; - int fill_cw = templ->fill_cw; - int fill_ccw = templ->fill_ccw; + int fill_front = templ->fill_front; + int fill_back = templ->fill_back; int fill = PIPE_POLYGON_MODE_FILL; + boolean offset_front = util_get_offset(templ, fill_front); + boolean offset_back = util_get_offset(templ, fill_back); + boolean offset = 0; - switch (templ->cull_mode) { - case PIPE_WINDING_BOTH: + switch (templ->cull_face) { + case PIPE_FACE_FRONT_AND_BACK: offset = 0; fill = PIPE_POLYGON_MODE_FILL; break; - case PIPE_WINDING_CW: - offset = offset_ccw; - fill = fill_ccw; + case PIPE_FACE_FRONT: + offset = offset_front; + fill = fill_front; break; - case PIPE_WINDING_CCW: - offset = offset_cw; - fill = fill_cw; + case PIPE_FACE_BACK: + offset = offset_back; + fill = fill_back; break; - case PIPE_WINDING_NONE: - if (fill_cw != fill_ccw || offset_cw != offset_ccw) + case PIPE_FACE_NONE: + if (fill_front != fill_back || offset_front != offset_back) { /* Always need the draw module to work out different * front/back fill modes: @@ -149,8 +150,8 @@ svga_create_rasterizer_state(struct pipe_context *pipe, rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; } else { - offset = offset_ccw; - fill = fill_ccw; + offset = offset_front; + fill = fill_front; } break; @@ -167,7 +168,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, (templ->flatshade || templ->light_twoside || offset || - templ->cull_mode != PIPE_WINDING_NONE)) + templ->cull_face != PIPE_FACE_NONE)) { fill = PIPE_POLYGON_MODE_FILL; rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; diff --git a/src/gallium/drivers/svga/svga_resource.c b/src/gallium/drivers/svga/svga_resource.c index ba630582e59..ef2a0c40f03 100644 --- a/src/gallium/drivers/svga/svga_resource.c +++ b/src/gallium/drivers/svga/svga_resource.c @@ -33,6 +33,7 @@ svga_resource_from_handle(struct pipe_screen * screen, void svga_init_resource_functions(struct svga_context *svga) { + svga->pipe.is_resource_referenced = u_is_resource_referenced_vtbl; svga->pipe.get_transfer = u_get_transfer_vtbl; svga->pipe.transfer_map = u_transfer_map_vtbl; svga->pipe.transfer_flush_region = u_transfer_flush_region_vtbl; diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index b24af329218..99b419178b0 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -84,7 +84,7 @@ svga_get_name( struct pipe_screen *pscreen ) static float -svga_get_paramf(struct pipe_screen *screen, int param) +svga_get_paramf(struct pipe_screen *screen, enum pipe_cap param) { struct svga_screen *svgascreen = svga_screen(screen); struct svga_winsys_screen *sws = svgascreen->sws; @@ -134,6 +134,8 @@ svga_get_paramf(struct pipe_screen *screen, int param) return MIN2(result.u, PIPE_MAX_COLOR_BUFS); case PIPE_CAP_OCCLUSION_QUERY: return 1; + case PIPE_CAP_TIMER_QUERY: + return 0; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; @@ -177,6 +179,57 @@ svga_get_paramf(struct pipe_screen *screen, int param) case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 0; + /* + * Fragment shader limits + */ + + case PIPE_CAP_MAX_FS_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_ALU_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_FS_TEX_INDIRECTIONS: + return svgascreen->use_ps30 ? 512 : 96; + case PIPE_CAP_MAX_FS_CONTROL_FLOW_DEPTH: + return SVGA3D_MAX_NESTING_LEVEL; + case PIPE_CAP_MAX_FS_INPUTS: + return 10; + case PIPE_CAP_MAX_FS_CONSTS: + return svgascreen->use_vs30 ? 224 : 16; + case PIPE_CAP_MAX_FS_TEMPS: + if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS, &result)) + return svgascreen->use_ps30 ? 32 : 12; + return result.u; + case PIPE_CAP_MAX_FS_ADDRS: + return svgascreen->use_ps30 ? 1 : 0; + case PIPE_CAP_MAX_FS_PREDS: + return svgascreen->use_ps30 ? 1 : 0; + + /* + * Vertex shader limits + */ + case PIPE_CAP_MAX_VS_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_ALU_INSTRUCTIONS: + if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS, &result)) + return svgascreen->use_vs30 ? 512 : 256; + return result.u; + case PIPE_CAP_MAX_VS_TEX_INSTRUCTIONS: + case PIPE_CAP_MAX_VS_TEX_INDIRECTIONS: + /* XXX: until we have vertex texture support */ + return 0; + case PIPE_CAP_MAX_VS_CONTROL_FLOW_DEPTH: + return SVGA3D_MAX_NESTING_LEVEL; + case PIPE_CAP_MAX_VS_INPUTS: + return 16; + case PIPE_CAP_MAX_VS_CONSTS: + return 256; + case PIPE_CAP_MAX_VS_TEMPS: + if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS, &result)) + return svgascreen->use_vs30 ? 32 : 12; + return result.u; + case PIPE_CAP_MAX_VS_ADDRS: + return svgascreen->use_vs30 ? 1 : 0; + case PIPE_CAP_MAX_VS_PREDS: + return svgascreen->use_vs30 ? 1 : 0; + default: return 0; } @@ -186,7 +239,7 @@ svga_get_paramf(struct pipe_screen *screen, int param) /* This is a fairly pointless interface */ static int -svga_get_param(struct pipe_screen *screen, int param) +svga_get_param(struct pipe_screen *screen, enum pipe_cap param) { return (int) svga_get_paramf( screen, param ); } diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c index 1310fd9825f..ad6f2947137 100644 --- a/src/gallium/drivers/svga/svga_state_fs.c +++ b/src/gallium/drivers/svga/svga_state_fs.c @@ -131,8 +131,7 @@ static int make_fs_key( const struct svga_context *svga, /* SVGA_NEW_RAST */ key->light_twoside = svga->curr.rast->templ.light_twoside; - key->front_cw = (svga->curr.rast->templ.front_winding == - PIPE_WINDING_CW); + key->front_ccw = svga->curr.rast->templ.front_ccw; } /* The blend workaround for simulating logicop xor behaviour diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c index b7195d246bc..ab13f3fdf19 100644 --- a/src/gallium/drivers/svga/svga_state_rss.c +++ b/src/gallium/drivers/svga/svga_state_rss.c @@ -146,13 +146,13 @@ static int emit_rss( struct svga_context *svga, * then our definition of front face agrees with hardware. * Otherwise need to flip. */ - if (rast->templ.front_winding == PIPE_WINDING_CW) { - cw = 0; - ccw = 1; + if (rast->templ.front_ccw) { + ccw = 0; + cw = 1; } else { - cw = 1; - ccw = 0; + ccw = 1; + cw = 0; } /* Twoside stencil diff --git a/src/gallium/drivers/svga/svga_surface.c b/src/gallium/drivers/svga/svga_surface.c index bd2cc380048..b21dc5fd9af 100644 --- a/src/gallium/drivers/svga/svga_surface.c +++ b/src/gallium/drivers/svga/svga_surface.c @@ -37,7 +37,6 @@ #include "svga_context.h" #include "svga_resource_texture.h" #include "svga_surface.h" -#include "svga_winsys.h" #include "svga_debug.h" diff --git a/src/gallium/drivers/svga/svga_swtnl.h b/src/gallium/drivers/svga/svga_swtnl.h index 8724690f7e1..65c675f99c9 100644 --- a/src/gallium/drivers/svga/svga_swtnl.h +++ b/src/gallium/drivers/svga/svga_swtnl.h @@ -30,7 +30,6 @@ struct svga_context; struct pipe_context; -struct pipe_buffer; struct vbuf_render; diff --git a/src/gallium/drivers/svga/svga_swtnl_backend.c b/src/gallium/drivers/svga/svga_swtnl_backend.c index b0cbead8a5c..ff3da842729 100644 --- a/src/gallium/drivers/svga/svga_swtnl_backend.c +++ b/src/gallium/drivers/svga/svga_swtnl_backend.c @@ -240,9 +240,9 @@ svga_vbuf_render_draw_arrays( struct vbuf_render *render, static void -svga_vbuf_render_draw( struct vbuf_render *render, - const ushort *indices, - uint nr_indices) +svga_vbuf_render_draw_elements( struct vbuf_render *render, + const ushort *indices, + uint nr_indices) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; @@ -341,7 +341,7 @@ svga_vbuf_render_create( struct svga_context *svga ) svga_render->base.map_vertices = svga_vbuf_render_map_vertices; svga_render->base.unmap_vertices = svga_vbuf_render_unmap_vertices; svga_render->base.set_primitive = svga_vbuf_render_set_primitive; - svga_render->base.draw = svga_vbuf_render_draw; + svga_render->base.draw_elements = svga_vbuf_render_draw_elements; svga_render->base.draw_arrays = svga_vbuf_render_draw_arrays; svga_render->base.release_vertices = svga_vbuf_render_release_vertices; svga_render->base.destroy = svga_vbuf_render_destroy; diff --git a/src/gallium/drivers/svga/svga_tgsi.h b/src/gallium/drivers/svga/svga_tgsi.h index 063c9cf4221..7ea909c37bf 100644 --- a/src/gallium/drivers/svga/svga_tgsi.h +++ b/src/gallium/drivers/svga/svga_tgsi.h @@ -48,7 +48,7 @@ struct svga_vs_compile_key struct svga_fs_compile_key { unsigned light_twoside:1; - unsigned front_cw:1; + unsigned front_ccw:1; unsigned white_fragments:1; unsigned num_textures:8; unsigned num_unnormalized_coords:8; diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c index 7d7024c4a7d..67e1f22a701 100644 --- a/src/gallium/drivers/svga/svga_tgsi_insn.c +++ b/src/gallium/drivers/svga/svga_tgsi_insn.c @@ -2588,10 +2588,10 @@ static boolean emit_light_twoside( struct svga_shader_emitter *emit ) if_token = inst_token( SVGA3DOP_IFC ); - if (emit->key.fkey.front_cw) - if_token.control = SVGA3DOPCOMP_GT; - else + if (emit->key.fkey.front_ccw) if_token.control = SVGA3DOPCOMP_LT; + else + if_token.control = SVGA3DOPCOMP_GT; zero = scalar(zero, TGSI_SWIZZLE_X); @@ -2639,12 +2639,12 @@ static boolean emit_frontface( struct svga_shader_emitter *emit ) temp = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); - if (emit->key.fkey.front_cw) { - pass = scalar( zero, TGSI_SWIZZLE_W ); - fail = scalar( zero, TGSI_SWIZZLE_X ); - } else { + if (emit->key.fkey.front_ccw) { pass = scalar( zero, TGSI_SWIZZLE_X ); fail = scalar( zero, TGSI_SWIZZLE_W ); + } else { + pass = scalar( zero, TGSI_SWIZZLE_W ); + fail = scalar( zero, TGSI_SWIZZLE_X ); } if (!emit_conditional(emit, PIPE_FUNC_GREATER, diff --git a/src/gallium/drivers/trace/Makefile b/src/gallium/drivers/trace/Makefile index 78f6347dc72..1b0c087a2a4 100644 --- a/src/gallium/drivers/trace/Makefile +++ b/src/gallium/drivers/trace/Makefile @@ -8,8 +8,6 @@ C_SOURCES = \ tr_dump.c \ tr_dump_state.c \ tr_screen.c \ - tr_state.c \ - tr_rbug.c \ tr_drm.c \ tr_texture.c diff --git a/src/gallium/drivers/trace/README b/src/gallium/drivers/trace/README index 203c3851bc3..cdcd8d2b4be 100644 --- a/src/gallium/drivers/trace/README +++ b/src/gallium/drivers/trace/README @@ -3,15 +3,15 @@ = About = -This directory contains a Gallium3D debugger pipe driver. -It can traces all incoming calls and/or provide remote debugging functionality. +This directory contains a Gallium3D trace debugger pipe driver. +It can traces all incoming calls. = Build Instructions = To build, invoke scons on the top dir as - scons dri=no statetrackers=mesa drivers=softpipe,i965simple,trace winsys=xlib + scons dri=no statetrackers=mesa winsys=xlib = Usage = @@ -36,40 +36,27 @@ Firefox or Internet Explorer. == Remote debugging == -For remote debugging +For remote debugging see: - export XMESA_TRACE=y - GALLIUM_RBUG=true progs/trivial/tri - -which should open gallium remote debugging session. While the program is running -you can launch the small remote debugging application from progs/rbug. More -information is in that directory. + src/gallium/drivers/rbug/README = Integrating = You can integrate the trace pipe driver either inside the state tracker or the -winsys. The procedure on both cases is the same. Let's assume you have a -pipe_screen and a pipe_context pair obtained by the usual means (variable and -function names are just for illustration purposes): +target. The procedure on both cases is the same. Let's assume you have a +pipe_screen obtained by the usual means (variable and function names are just +for illustration purposes): real_screen = real_screen_create(...); - real_context = real_context_create(...); - -The trace screen and pipe_context is then created by doing +The trace screen is then created by doing trace_screen = trace_screen_create(real_screen); - - trace_context = trace_context_create(trace_screen, real_context); - -You can then simply use trace_screen and trace_context instead of real_screen -and real_context. -Do not call trace_winsys_create. Simply pass trace_screen->winsys or -trace_context->winsys in places you would pass winsys. +You can then simply use trace_screen instead of real_screen. -You can create as many contexts you wish. Just ensure that you don't mistake -trace_screen with real_screen when creating them. +You can create as many contexts you wish from trace_screen::context_create they +are automatically wrapped by trace_screen. -- diff --git a/src/gallium/drivers/trace/SConscript b/src/gallium/drivers/trace/SConscript index 5f1fb17966a..0dc43a9ec41 100644 --- a/src/gallium/drivers/trace/SConscript +++ b/src/gallium/drivers/trace/SConscript @@ -10,8 +10,6 @@ trace = env.ConvenienceLibrary( 'tr_dump.c', 'tr_dump_state.c', 'tr_screen.c', - 'tr_state.c', - 'tr_rbug.c', 'tr_texture.c', ]) diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index 64a4316984b..5cc244d4b77 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -28,16 +28,16 @@ #include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_simple_list.h" -#include "util/u_format.h" #include "pipe/p_format.h" #include "pipe/p_screen.h" #include "tr_dump.h" #include "tr_dump_state.h" -#include "tr_state.h" +#include "tr_public.h" #include "tr_screen.h" #include "tr_texture.h" +#include "tr_context.h" @@ -83,82 +83,12 @@ trace_surface_unwrap(struct trace_context *tr_ctx, static INLINE void -trace_context_draw_block(struct trace_context *tr_ctx, int flag) -{ - int k; - - pipe_mutex_lock(tr_ctx->draw_mutex); - - if (tr_ctx->draw_blocker & flag) { - tr_ctx->draw_blocked |= flag; - } else if ((tr_ctx->draw_rule.blocker & flag) && - (tr_ctx->draw_blocker & 4)) { - boolean block = FALSE; - debug_printf("%s (%p %p) (%p %p) (%p %u) (%p %u)\n", __FUNCTION__, - (void *) tr_ctx->draw_rule.fs, (void *) tr_ctx->curr.fs, - (void *) tr_ctx->draw_rule.vs, (void *) tr_ctx->curr.vs, - (void *) tr_ctx->draw_rule.surf, 0, - (void *) tr_ctx->draw_rule.sampler_view, 0); - if (tr_ctx->draw_rule.fs && - tr_ctx->draw_rule.fs == tr_ctx->curr.fs) - block = TRUE; - if (tr_ctx->draw_rule.vs && - tr_ctx->draw_rule.vs == tr_ctx->curr.vs) - block = TRUE; - if (tr_ctx->draw_rule.surf && - tr_ctx->draw_rule.surf == tr_ctx->curr.zsbuf) - block = TRUE; - if (tr_ctx->draw_rule.surf) - for (k = 0; k < tr_ctx->curr.nr_cbufs; k++) - if (tr_ctx->draw_rule.surf == tr_ctx->curr.cbufs[k]) - block = TRUE; - if (tr_ctx->draw_rule.sampler_view) { - for (k = 0; k < tr_ctx->curr.num_sampler_views; k++) - if (tr_ctx->draw_rule.sampler_view == tr_ctx->curr.sampler_views[k]) - block = TRUE; - for (k = 0; k < tr_ctx->curr.num_vert_sampler_views; k++) { - if (tr_ctx->draw_rule.sampler_view == tr_ctx->curr.vert_sampler_views[k]) { - block = TRUE; - } - } - } - - if (block) - tr_ctx->draw_blocked |= (flag | 4); - } - - if (tr_ctx->draw_blocked) - trace_rbug_notify_draw_blocked(tr_ctx); - - /* wait for rbug to clear the blocked flag */ - while (tr_ctx->draw_blocked & flag) { - tr_ctx->draw_blocked |= flag; -#ifdef PIPE_THREAD_HAVE_CONDVAR - pipe_condvar_wait(tr_ctx->draw_cond, tr_ctx->draw_mutex); -#else - pipe_mutex_unlock(tr_ctx->draw_mutex); -#ifdef PIPE_SUBSYSTEM_WINDOWS_USER - Sleep(1); -#endif - pipe_mutex_lock(tr_ctx->draw_mutex); -#endif - } - - pipe_mutex_unlock(tr_ctx->draw_mutex); -} - -static INLINE void trace_context_draw_arrays(struct pipe_context *_pipe, unsigned mode, unsigned start, unsigned count) { struct trace_context *tr_ctx = trace_context(_pipe); struct pipe_context *pipe = tr_ctx->pipe; - if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled) - return; - - trace_context_draw_block(tr_ctx, 1); - trace_dump_call_begin("pipe_context", "draw_arrays"); trace_dump_arg(ptr, pipe); @@ -169,8 +99,6 @@ trace_context_draw_arrays(struct pipe_context *_pipe, pipe->draw_arrays(pipe, mode, start, count); trace_dump_call_end(); - - trace_context_draw_block(tr_ctx, 2); } @@ -185,11 +113,6 @@ trace_context_draw_elements(struct pipe_context *_pipe, struct pipe_context *pipe = tr_ctx->pipe; struct pipe_resource *indexBuffer = tr_buf->resource; - if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled) - return; - - trace_context_draw_block(tr_ctx, 1); - trace_dump_call_begin("pipe_context", "draw_elements"); trace_dump_arg(ptr, pipe); @@ -204,8 +127,6 @@ trace_context_draw_elements(struct pipe_context *_pipe, mode, start, count); trace_dump_call_end(); - - trace_context_draw_block(tr_ctx, 2); } @@ -225,11 +146,6 @@ trace_context_draw_range_elements(struct pipe_context *_pipe, struct pipe_context *pipe = tr_ctx->pipe; struct pipe_resource *indexBuffer = tr_buf->resource; - if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled) - return; - - trace_context_draw_block(tr_ctx, 1); - trace_dump_call_begin("pipe_context", "draw_range_elements"); trace_dump_arg(ptr, pipe); @@ -248,8 +164,6 @@ trace_context_draw_range_elements(struct pipe_context *_pipe, mode, start, count); trace_dump_call_end(); - - trace_context_draw_block(tr_ctx, 2); } @@ -634,31 +548,22 @@ trace_context_create_fs_state(struct pipe_context *_pipe, trace_dump_call_end(); - result = trace_shader_create(tr_ctx, state, result, TRACE_SHADER_FRAGMENT); - return result; } static INLINE void trace_context_bind_fs_state(struct pipe_context *_pipe, - void *_state) + void *state) { struct trace_context *tr_ctx = trace_context(_pipe); - struct trace_shader *tr_shdr = trace_shader(_state); struct pipe_context *pipe = tr_ctx->pipe; - void *state = tr_shdr ? tr_shdr->state : NULL; trace_dump_call_begin("pipe_context", "bind_fs_state"); trace_dump_arg(ptr, pipe); trace_dump_arg(ptr, state); - tr_ctx->curr.fs = tr_shdr; - - if (tr_shdr && tr_shdr->replaced) - state = tr_shdr->replaced; - pipe->bind_fs_state(pipe, state); trace_dump_call_end(); @@ -667,12 +572,10 @@ trace_context_bind_fs_state(struct pipe_context *_pipe, static INLINE void trace_context_delete_fs_state(struct pipe_context *_pipe, - void *_state) + void *state) { struct trace_context *tr_ctx = trace_context(_pipe); - struct trace_shader *tr_shdr = trace_shader(_state); struct pipe_context *pipe = tr_ctx->pipe; - void *state = tr_shdr->state; trace_dump_call_begin("pipe_context", "delete_fs_state"); @@ -682,8 +585,6 @@ trace_context_delete_fs_state(struct pipe_context *_pipe, pipe->delete_fs_state(pipe, state); trace_dump_call_end(); - - trace_shader_destroy(tr_ctx, tr_shdr); } @@ -706,31 +607,22 @@ trace_context_create_vs_state(struct pipe_context *_pipe, trace_dump_call_end(); - result = trace_shader_create(tr_ctx, state, result, TRACE_SHADER_VERTEX); - return result; } static INLINE void trace_context_bind_vs_state(struct pipe_context *_pipe, - void *_state) + void *state) { struct trace_context *tr_ctx = trace_context(_pipe); - struct trace_shader *tr_shdr = trace_shader(_state); struct pipe_context *pipe = tr_ctx->pipe; - void *state = tr_shdr ? tr_shdr->state : NULL; trace_dump_call_begin("pipe_context", "bind_vs_state"); trace_dump_arg(ptr, pipe); trace_dump_arg(ptr, state); - tr_ctx->curr.vs = tr_shdr; - - if (tr_shdr && tr_shdr->replaced) - state = tr_shdr->replaced; - pipe->bind_vs_state(pipe, state); trace_dump_call_end(); @@ -739,12 +631,10 @@ trace_context_bind_vs_state(struct pipe_context *_pipe, static INLINE void trace_context_delete_vs_state(struct pipe_context *_pipe, - void *_state) + void *state) { struct trace_context *tr_ctx = trace_context(_pipe); - struct trace_shader *tr_shdr = trace_shader(_state); struct pipe_context *pipe = tr_ctx->pipe; - void *state = tr_shdr->state; trace_dump_call_begin("pipe_context", "delete_vs_state"); @@ -754,8 +644,6 @@ trace_context_delete_vs_state(struct pipe_context *_pipe, pipe->delete_vs_state(pipe, state); trace_dump_call_end(); - - trace_shader_destroy(tr_ctx, tr_shdr); } @@ -927,18 +815,6 @@ trace_context_set_framebuffer_state(struct pipe_context *_pipe, struct pipe_framebuffer_state unwrapped_state; unsigned i; - { - tr_ctx->curr.nr_cbufs = state->nr_cbufs; - for (i = 0; i < state->nr_cbufs; i++) - if (state->cbufs[i]) - tr_ctx->curr.cbufs[i] = trace_resource(state->cbufs[i]->texture); - else - tr_ctx->curr.cbufs[i] = NULL; - if (state->zsbuf) - tr_ctx->curr.zsbuf = trace_resource(state->zsbuf->texture); - else - tr_ctx->curr.zsbuf = NULL; - } /* Unwrap the input state */ memcpy(&unwrapped_state, state, sizeof(unwrapped_state)); @@ -1088,10 +964,8 @@ trace_context_set_fragment_sampler_views(struct pipe_context *_pipe, struct pipe_sampler_view *unwrapped_views[PIPE_MAX_SAMPLERS]; unsigned i; - tr_ctx->curr.num_sampler_views = num; for(i = 0; i < num; ++i) { tr_view = trace_sampler_view(views[i]); - tr_ctx->curr.sampler_views[i] = tr_view; unwrapped_views[i] = tr_view ? tr_view->sampler_view : NULL; } views = unwrapped_views; @@ -1119,10 +993,8 @@ trace_context_set_vertex_sampler_views(struct pipe_context *_pipe, struct pipe_sampler_view *unwrapped_views[PIPE_MAX_VERTEX_SAMPLERS]; unsigned i; - tr_ctx->curr.num_vert_sampler_views = num; for(i = 0; i < num; ++i) { tr_view = trace_sampler_view(views[i]); - tr_ctx->curr.vert_sampler_views[i] = tr_view; unwrapped_views[i] = tr_view ? tr_view->sampler_view : NULL; } views = unwrapped_views; @@ -1293,7 +1165,6 @@ trace_context_flush(struct pipe_context *_pipe, static INLINE void trace_context_destroy(struct pipe_context *_pipe) { - struct trace_screen *tr_scr = trace_screen(_pipe->screen); struct trace_context *tr_ctx = trace_context(_pipe); struct pipe_context *pipe = tr_ctx->pipe; @@ -1301,8 +1172,6 @@ trace_context_destroy(struct pipe_context *_pipe) trace_dump_arg(ptr, pipe); trace_dump_call_end(); - trace_screen_remove_from_list(tr_scr, contexts, tr_ctx); - pipe->destroy(pipe); FREE(tr_ctx); @@ -1535,13 +1404,6 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.winsys = NULL; tr_ctx->base.priv = pipe->priv; /* expose wrapped priv data */ tr_ctx->base.screen = &tr_scr->base; - tr_ctx->draw_blocker = debug_get_flags_option("RBUG_BLOCK", - rbug_blocker_flags, - 0); - pipe_mutex_init(tr_ctx->draw_mutex); - pipe_condvar_init(tr_ctx->draw_cond); - pipe_mutex_init(tr_ctx->list_mutex); - make_empty_list(&tr_ctx->shaders); tr_ctx->base.destroy = trace_context_destroy; tr_ctx->base.draw_arrays = trace_context_draw_arrays; @@ -1603,8 +1465,6 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->pipe = pipe; - trace_screen_add_to_list(tr_scr, contexts, tr_ctx); - return &tr_ctx->base; error1: diff --git a/src/gallium/drivers/trace/tr_context.h b/src/gallium/drivers/trace/tr_context.h index 1b4121d80a9..dadbe561180 100644 --- a/src/gallium/drivers/trace/tr_context.h +++ b/src/gallium/drivers/trace/tr_context.h @@ -47,45 +47,6 @@ struct trace_context struct pipe_context base; struct pipe_context *pipe; - - /* current state */ - struct { - struct trace_shader *fs; - struct trace_shader *vs; - - struct trace_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; - unsigned num_sampler_views; - - struct trace_sampler_view *vert_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; - unsigned num_vert_sampler_views; - - unsigned nr_cbufs; - struct trace_resource *cbufs[PIPE_MAX_COLOR_BUFS]; - struct trace_resource *zsbuf; - } curr; - - struct { - struct trace_shader *fs; - struct trace_shader *vs; - - struct trace_sampler_view *sampler_view; - struct trace_resource *surf; - - int blocker; - } draw_rule; - unsigned draw_num_rules; - pipe_condvar draw_cond; - pipe_mutex draw_mutex; - int draw_blocker; - int draw_blocked; - - /* for list on screen */ - struct tr_list list; - - /* list of state objects */ - pipe_mutex list_mutex; - unsigned num_shaders; - struct tr_list shaders; }; @@ -101,9 +62,6 @@ struct pipe_context * trace_context_create(struct trace_screen *tr_scr, struct pipe_context *pipe); -void -trace_rbug_notify_draw_blocked(struct trace_context *tr_ctx); - #ifdef __cplusplus } diff --git a/src/gallium/drivers/trace/tr_drm.c b/src/gallium/drivers/trace/tr_drm.c index 0dc8cca2648..9c7d39201a9 100644 --- a/src/gallium/drivers/trace/tr_drm.c +++ b/src/gallium/drivers/trace/tr_drm.c @@ -28,6 +28,7 @@ #include "state_tracker/drm_api.h" #include "util/u_memory.h" +#include "rbug/rbug_public.h" #include "tr_drm.h" #include "tr_screen.h" #include "tr_public.h" @@ -61,7 +62,7 @@ trace_drm_create_screen(struct drm_api *_api, int fd, screen = api->create_screen(api, fd, arg); - return trace_screen_create(screen); + return trace_screen_create(rbug_screen_create(screen)); } static void @@ -84,7 +85,7 @@ trace_drm_create(struct drm_api *api) if (!api) goto error; - if (!trace_enabled()) + if (!trace_enabled() && !rbug_enabled()) goto error; tr_api = CALLOC_STRUCT(trace_drm_api); diff --git a/src/gallium/drivers/trace/tr_dump.h b/src/gallium/drivers/trace/tr_dump.h index f21f72b0c79..74c5e83e9e1 100644 --- a/src/gallium/drivers/trace/tr_dump.h +++ b/src/gallium/drivers/trace/tr_dump.h @@ -37,7 +37,6 @@ #include "pipe/p_compiler.h" #include "pipe/p_format.h" -struct pipe_buffer; struct pipe_resource; struct pipe_surface; struct pipe_transfer; diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c index f148a859ff3..1727c2a0206 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -136,12 +136,13 @@ void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state) trace_dump_member(bool, state, flatshade); trace_dump_member(bool, state, light_twoside); - trace_dump_member(uint, state, front_winding); - trace_dump_member(uint, state, cull_mode); - trace_dump_member(uint, state, fill_cw); - trace_dump_member(uint, state, fill_ccw); - trace_dump_member(bool, state, offset_cw); - trace_dump_member(bool, state, offset_ccw); + trace_dump_member(uint, state, front_ccw); + trace_dump_member(uint, state, cull_face); + trace_dump_member(uint, state, fill_front); + trace_dump_member(uint, state, fill_back); + trace_dump_member(bool, state, offset_point); + trace_dump_member(bool, state, offset_line); + trace_dump_member(bool, state, offset_tri); trace_dump_member(bool, state, scissor); trace_dump_member(bool, state, poly_smooth); trace_dump_member(bool, state, poly_stipple_enable); diff --git a/src/gallium/drivers/trace/tr_public.h b/src/gallium/drivers/trace/tr_public.h index 62e217097d0..aee4937dd4f 100644 --- a/src/gallium/drivers/trace/tr_public.h +++ b/src/gallium/drivers/trace/tr_public.h @@ -38,6 +38,9 @@ struct pipe_context; struct pipe_screen * trace_screen_create(struct pipe_screen *screen); +boolean +trace_enabled(void); + #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/trace/tr_rbug.c b/src/gallium/drivers/trace/tr_rbug.c deleted file mode 100644 index 3ce1b85854b..00000000000 --- a/src/gallium/drivers/trace/tr_rbug.c +++ /dev/null @@ -1,864 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * 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 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -#include "os/os_thread.h" -#include "util/u_format.h" -#include "util/u_string.h" -#include "util/u_inlines.h" -#include "util/u_memory.h" -#include "util/u_simple_list.h" -#include "util/u_network.h" -#include "os/os_time.h" - -#include "tgsi/tgsi_parse.h" - -#include "tr_dump.h" -#include "tr_state.h" -#include "tr_texture.h" - -#include "rbug/rbug.h" - -#include <errno.h> - -#define U642VOID(x) ((void *)(unsigned long)(x)) -#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) - -struct trace_rbug -{ - struct trace_screen *tr_scr; - struct rbug_connection *con; - pipe_thread thread; - boolean running; -}; - -PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug); - - -/********************************************************** - * Helper functions - */ - - -static struct trace_context * -trace_rbug_get_context_locked(struct trace_screen *tr_scr, rbug_context_t ctx) -{ - struct trace_context *tr_ctx = NULL; - struct tr_list *ptr; - - foreach(ptr, &tr_scr->contexts) { - tr_ctx = (struct trace_context *)((char*)ptr - offsetof(struct trace_context, list)); - if (ctx == VOID2U64(tr_ctx)) - break; - tr_ctx = NULL; - } - - return tr_ctx; -} - -static struct trace_shader * -trace_rbug_get_shader_locked(struct trace_context *tr_ctx, rbug_shader_t shdr) -{ - struct trace_shader *tr_shdr = NULL; - struct tr_list *ptr; - - foreach(ptr, &tr_ctx->shaders) { - tr_shdr = (struct trace_shader *)((char*)ptr - offsetof(struct trace_shader, list)); - if (shdr == VOID2U64(tr_shdr)) - break; - tr_shdr = NULL; - } - - return tr_shdr; -} - -static void * -trace_shader_create_locked(struct pipe_context *pipe, - struct trace_shader *tr_shdr, - struct tgsi_token *tokens) -{ - void *state = NULL; - struct pipe_shader_state pss = { 0 }; - pss.tokens = tokens; - - if (tr_shdr->type == TRACE_SHADER_FRAGMENT) { - state = pipe->create_fs_state(pipe, &pss); - } else if (tr_shdr->type == TRACE_SHADER_VERTEX) { - state = pipe->create_vs_state(pipe, &pss); - } else - assert(0); - - return state; -} - -static void -trace_shader_bind_locked(struct pipe_context *pipe, - struct trace_shader *tr_shdr, - void *state) -{ - if (tr_shdr->type == TRACE_SHADER_FRAGMENT) { - pipe->bind_fs_state(pipe, state); - } else if (tr_shdr->type == TRACE_SHADER_VERTEX) { - pipe->bind_vs_state(pipe, state); - } else - assert(0); -} - -static void -trace_shader_delete_locked(struct pipe_context *pipe, - struct trace_shader *tr_shdr, - void *state) -{ - if (tr_shdr->type == TRACE_SHADER_FRAGMENT) { - pipe->delete_fs_state(pipe, state); - } else if (tr_shdr->type == TRACE_SHADER_VERTEX) { - pipe->delete_vs_state(pipe, state); - } else - assert(0); -} - -/************************************************ - * Request handler functions - */ - - -static int -trace_rbug_texture_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_resource *tr_tex = NULL; - struct tr_list *ptr; - rbug_texture_t *texs; - int i = 0; - - pipe_mutex_lock(tr_scr->list_mutex); - texs = MALLOC(tr_scr->num_textures * sizeof(rbug_texture_t)); - foreach(ptr, &tr_scr->textures) { - tr_tex = (struct trace_resource *)((char*)ptr - offsetof(struct trace_resource, list)); - texs[i++] = VOID2U64(tr_tex); - } - pipe_mutex_unlock(tr_scr->list_mutex); - - rbug_send_texture_list_reply(tr_rbug->con, serial, texs, i, NULL); - FREE(texs); - - return 0; -} - -static int -trace_rbug_texture_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_resource *tr_tex = NULL; - struct rbug_proto_texture_info *gpti = (struct rbug_proto_texture_info *)header; - struct tr_list *ptr; - struct pipe_resource *t; - - pipe_mutex_lock(tr_scr->list_mutex); - foreach(ptr, &tr_scr->textures) { - tr_tex = (struct trace_resource *)((char*)ptr - offsetof(struct trace_resource, list)); - if (gpti->texture == VOID2U64(tr_tex)) - break; - tr_tex = NULL; - } - - if (!tr_tex) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - t = tr_tex->resource; - rbug_send_texture_info_reply(tr_rbug->con, serial, - t->target, t->format, - &t->width0, 1, - &t->height0, 1, - &t->depth0, 1, - util_format_get_blockwidth(t->format), - util_format_get_blockheight(t->format), - util_format_get_blocksize(t->format), - t->last_level, - t->nr_samples, - t->bind, - NULL); - - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; -} - -static int -trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_resource *tr_tex = NULL; - struct tr_list *ptr; - - struct pipe_context *context = tr_scr->private_context; - struct pipe_resource *tex; - struct pipe_transfer *t; - - void *map; - - pipe_mutex_lock(tr_scr->list_mutex); - foreach(ptr, &tr_scr->textures) { - tr_tex = (struct trace_resource *)((char*)ptr - offsetof(struct trace_resource, list)); - if (gptr->texture == VOID2U64(tr_tex)) - break; - tr_tex = NULL; - } - - if (!tr_tex) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - tex = tr_tex->resource; - t = pipe_get_transfer(context, tex, - gptr->face, gptr->level, gptr->zslice, - PIPE_TRANSFER_READ, - gptr->x, gptr->y, gptr->w, gptr->h); - - map = context->transfer_map(context, t); - - rbug_send_texture_read_reply(tr_rbug->con, serial, - t->resource->format, - util_format_get_blockwidth(t->resource->format), - util_format_get_blockheight(t->resource->format), - util_format_get_blocksize(t->resource->format), - (uint8_t*)map, - t->stride * util_format_get_nblocksy(t->resource->format, - t->box.height), - t->stride, - NULL); - - context->transfer_unmap(context, t); - context->transfer_destroy(context, t); - - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; -} - -static int -trace_rbug_context_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct tr_list *ptr; - struct trace_context *tr_ctx = NULL; - rbug_context_t *ctxs; - int i = 0; - - pipe_mutex_lock(tr_scr->list_mutex); - ctxs = MALLOC(tr_scr->num_contexts * sizeof(rbug_context_t)); - foreach(ptr, &tr_scr->contexts) { - tr_ctx = (struct trace_context *)((char*)ptr - offsetof(struct trace_context, list)); - ctxs[i++] = VOID2U64(tr_ctx); - } - pipe_mutex_unlock(tr_scr->list_mutex); - - rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL); - FREE(ctxs); - - return 0; -} - -static int -trace_rbug_context_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_context *tr_ctx = NULL; - rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS]; - rbug_texture_t texs[PIPE_MAX_SAMPLERS]; - int i; - - pipe_mutex_lock(tr_scr->list_mutex); - tr_ctx = trace_rbug_get_context_locked(tr_scr, info->context); - - if (!tr_ctx) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - /* protect the pipe context */ - pipe_mutex_lock(tr_ctx->draw_mutex); - trace_dump_call_lock(); - - for (i = 0; i < tr_ctx->curr.nr_cbufs; i++) - cbufs[i] = VOID2U64(tr_ctx->curr.cbufs[i]); - - for (i = 0; i < tr_ctx->curr.num_sampler_views; i++) - texs[i] = VOID2U64(tr_ctx->curr.sampler_views[i]); - - rbug_send_context_info_reply(tr_rbug->con, serial, - VOID2U64(tr_ctx->curr.vs), VOID2U64(tr_ctx->curr.fs), - texs, tr_ctx->curr.num_sampler_views, - cbufs, tr_ctx->curr.nr_cbufs, - VOID2U64(tr_ctx->curr.zsbuf), - tr_ctx->draw_blocker, tr_ctx->draw_blocked, NULL); - - trace_dump_call_unlock(); - pipe_mutex_unlock(tr_ctx->draw_mutex); - - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; -} - -static int -trace_rbug_context_draw_block(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct rbug_proto_context_draw_block *block = (struct rbug_proto_context_draw_block *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_context *tr_ctx = NULL; - - pipe_mutex_lock(tr_scr->list_mutex); - tr_ctx = trace_rbug_get_context_locked(tr_scr, block->context); - - if (!tr_ctx) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - pipe_mutex_lock(tr_ctx->draw_mutex); - tr_ctx->draw_blocker |= block->block; - pipe_mutex_unlock(tr_ctx->draw_mutex); - - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; -} - -static int -trace_rbug_context_draw_step(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct rbug_proto_context_draw_step *step = (struct rbug_proto_context_draw_step *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_context *tr_ctx = NULL; - - pipe_mutex_lock(tr_scr->list_mutex); - tr_ctx = trace_rbug_get_context_locked(tr_scr, step->context); - - if (!tr_ctx) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - pipe_mutex_lock(tr_ctx->draw_mutex); - if (tr_ctx->draw_blocked & RBUG_BLOCK_RULE) { - if (step->step & RBUG_BLOCK_RULE) - tr_ctx->draw_blocked &= ~RBUG_BLOCK_MASK; - } else { - tr_ctx->draw_blocked &= ~step->step; - } - pipe_mutex_unlock(tr_ctx->draw_mutex); - -#ifdef PIPE_THREAD_HAVE_CONDVAR - pipe_condvar_broadcast(tr_ctx->draw_cond); -#endif - - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; -} - -static int -trace_rbug_context_draw_unblock(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct rbug_proto_context_draw_unblock *unblock = (struct rbug_proto_context_draw_unblock *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_context *tr_ctx = NULL; - - pipe_mutex_lock(tr_scr->list_mutex); - tr_ctx = trace_rbug_get_context_locked(tr_scr, unblock->context); - - if (!tr_ctx) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - pipe_mutex_lock(tr_ctx->draw_mutex); - if (tr_ctx->draw_blocked & RBUG_BLOCK_RULE) { - if (unblock->unblock & RBUG_BLOCK_RULE) - tr_ctx->draw_blocked &= ~RBUG_BLOCK_MASK; - } else { - tr_ctx->draw_blocked &= ~unblock->unblock; - } - tr_ctx->draw_blocker &= ~unblock->unblock; - pipe_mutex_unlock(tr_ctx->draw_mutex); - -#ifdef PIPE_THREAD_HAVE_CONDVAR - pipe_condvar_broadcast(tr_ctx->draw_cond); -#endif - - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; -} - -static int -trace_rbug_context_draw_rule(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct rbug_proto_context_draw_rule *rule = (struct rbug_proto_context_draw_rule *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_context *tr_ctx = NULL; - - pipe_mutex_lock(tr_scr->list_mutex); - tr_ctx = trace_rbug_get_context_locked(tr_scr, rule->context); - - if (!tr_ctx) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - pipe_mutex_lock(tr_ctx->draw_mutex); - tr_ctx->draw_rule.vs = U642VOID(rule->vertex); - tr_ctx->draw_rule.fs = U642VOID(rule->fragment); - tr_ctx->draw_rule.sampler_view = U642VOID(rule->texture); - tr_ctx->draw_rule.surf = U642VOID(rule->surface); - tr_ctx->draw_rule.blocker = rule->block; - tr_ctx->draw_blocker |= RBUG_BLOCK_RULE; - pipe_mutex_unlock(tr_ctx->draw_mutex); - -#ifdef PIPE_THREAD_HAVE_CONDVAR - pipe_condvar_broadcast(tr_ctx->draw_cond); -#endif - - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; -} - -static int -trace_rbug_context_flush(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct rbug_proto_context_flush *flush = (struct rbug_proto_context_flush *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_context *tr_ctx = NULL; - - pipe_mutex_lock(tr_scr->list_mutex); - tr_ctx = trace_rbug_get_context_locked(tr_scr, flush->context); - - if (!tr_ctx) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - /* protect the pipe context */ - trace_dump_call_lock(); - - tr_ctx->pipe->flush(tr_ctx->pipe, flush->flags, NULL); - - trace_dump_call_unlock(); - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; -} - -static int -trace_rbug_shader_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct rbug_proto_shader_list *list = (struct rbug_proto_shader_list *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_context *tr_ctx = NULL; - struct trace_shader *tr_shdr = NULL; - struct tr_list *ptr; - rbug_shader_t *shdrs; - int i = 0; - - pipe_mutex_lock(tr_scr->list_mutex); - tr_ctx = trace_rbug_get_context_locked(tr_scr, list->context); - - if (!tr_ctx) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - pipe_mutex_lock(tr_ctx->list_mutex); - shdrs = MALLOC(tr_ctx->num_shaders * sizeof(rbug_shader_t)); - foreach(ptr, &tr_ctx->shaders) { - tr_shdr = (struct trace_shader *)((char*)ptr - offsetof(struct trace_shader, list)); - shdrs[i++] = VOID2U64(tr_shdr); - } - - pipe_mutex_unlock(tr_ctx->list_mutex); - pipe_mutex_unlock(tr_scr->list_mutex); - - rbug_send_shader_list_reply(tr_rbug->con, serial, shdrs, i, NULL); - FREE(shdrs); - - return 0; -} - -static int -trace_rbug_shader_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - struct rbug_proto_shader_info *info = (struct rbug_proto_shader_info *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_context *tr_ctx = NULL; - struct trace_shader *tr_shdr = NULL; - unsigned original_len; - unsigned replaced_len; - - pipe_mutex_lock(tr_scr->list_mutex); - tr_ctx = trace_rbug_get_context_locked(tr_scr, info->context); - - if (!tr_ctx) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - pipe_mutex_lock(tr_ctx->list_mutex); - - tr_shdr = trace_rbug_get_shader_locked(tr_ctx, info->shader); - - if (!tr_shdr) { - pipe_mutex_unlock(tr_ctx->list_mutex); - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - /* just in case */ - assert(sizeof(struct tgsi_token) == 4); - - original_len = tgsi_num_tokens(tr_shdr->tokens); - if (tr_shdr->replaced_tokens) - replaced_len = tgsi_num_tokens(tr_shdr->replaced_tokens); - else - replaced_len = 0; - - rbug_send_shader_info_reply(tr_rbug->con, serial, - (uint32_t*)tr_shdr->tokens, original_len, - (uint32_t*)tr_shdr->replaced_tokens, replaced_len, - tr_shdr->disabled, - NULL); - - pipe_mutex_unlock(tr_ctx->list_mutex); - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; -} - -static int -trace_rbug_shader_disable(struct trace_rbug *tr_rbug, struct rbug_header *header) -{ - struct rbug_proto_shader_disable *dis = (struct rbug_proto_shader_disable *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_context *tr_ctx = NULL; - struct trace_shader *tr_shdr = NULL; - - pipe_mutex_lock(tr_scr->list_mutex); - tr_ctx = trace_rbug_get_context_locked(tr_scr, dis->context); - - if (!tr_ctx) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - pipe_mutex_lock(tr_ctx->list_mutex); - - tr_shdr = trace_rbug_get_shader_locked(tr_ctx, dis->shader); - - if (!tr_shdr) { - pipe_mutex_unlock(tr_ctx->list_mutex); - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - tr_shdr->disabled = dis->disable; - - pipe_mutex_unlock(tr_ctx->list_mutex); - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; -} - -static int -trace_rbug_shader_replace(struct trace_rbug *tr_rbug, struct rbug_header *header) -{ - struct rbug_proto_shader_replace *rep = (struct rbug_proto_shader_replace *)header; - - struct trace_screen *tr_scr = tr_rbug->tr_scr; - struct trace_context *tr_ctx = NULL; - struct trace_shader *tr_shdr = NULL; - struct pipe_context *pipe = NULL; - void *state; - - pipe_mutex_lock(tr_scr->list_mutex); - tr_ctx = trace_rbug_get_context_locked(tr_scr, rep->context); - - if (!tr_ctx) { - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - pipe_mutex_lock(tr_ctx->list_mutex); - - tr_shdr = trace_rbug_get_shader_locked(tr_ctx, rep->shader); - - if (!tr_shdr) { - pipe_mutex_unlock(tr_ctx->list_mutex); - pipe_mutex_unlock(tr_scr->list_mutex); - return -ESRCH; - } - - /* protect the pipe context */ - trace_dump_call_lock(); - - pipe = tr_ctx->pipe; - - /* remove old replaced shader */ - if (tr_shdr->replaced) { - if (tr_ctx->curr.fs == tr_shdr || tr_ctx->curr.vs == tr_shdr) - trace_shader_bind_locked(pipe, tr_shdr, tr_shdr->state); - - FREE(tr_shdr->replaced_tokens); - trace_shader_delete_locked(pipe, tr_shdr, tr_shdr->replaced); - tr_shdr->replaced = NULL; - tr_shdr->replaced_tokens = NULL; - } - - /* empty inputs means restore old which we did above */ - if (rep->tokens_len == 0) - goto out; - - tr_shdr->replaced_tokens = tgsi_dup_tokens((struct tgsi_token *)rep->tokens); - if (!tr_shdr->replaced_tokens) - goto err; - - state = trace_shader_create_locked(pipe, tr_shdr, tr_shdr->replaced_tokens); - if (!state) - goto err; - - /* bind new shader if the shader is currently a bound */ - if (tr_ctx->curr.fs == tr_shdr || tr_ctx->curr.vs == tr_shdr) - trace_shader_bind_locked(pipe, tr_shdr, state); - - /* save state */ - tr_shdr->replaced = state; - -out: - trace_dump_call_unlock(); - pipe_mutex_unlock(tr_ctx->list_mutex); - pipe_mutex_unlock(tr_scr->list_mutex); - - return 0; - -err: - FREE(tr_shdr->replaced_tokens); - tr_shdr->replaced = NULL; - tr_shdr->replaced_tokens = NULL; - - trace_dump_call_unlock(); - pipe_mutex_unlock(tr_ctx->list_mutex); - pipe_mutex_unlock(tr_scr->list_mutex); - return -EINVAL; -} - -static boolean -trace_rbug_header(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) -{ - int ret = 0; - - switch(header->opcode) { - case RBUG_OP_PING: - rbug_send_ping_reply(tr_rbug->con, serial, NULL); - break; - case RBUG_OP_TEXTURE_LIST: - ret = trace_rbug_texture_list(tr_rbug, header, serial); - break; - case RBUG_OP_TEXTURE_INFO: - ret = trace_rbug_texture_info(tr_rbug, header, serial); - break; - case RBUG_OP_TEXTURE_READ: - ret = trace_rbug_texture_read(tr_rbug, header, serial); - break; - case RBUG_OP_CONTEXT_LIST: - ret = trace_rbug_context_list(tr_rbug, header, serial); - break; - case RBUG_OP_CONTEXT_INFO: - ret = trace_rbug_context_info(tr_rbug, header, serial); - break; - case RBUG_OP_CONTEXT_DRAW_BLOCK: - ret = trace_rbug_context_draw_block(tr_rbug, header, serial); - break; - case RBUG_OP_CONTEXT_DRAW_STEP: - ret = trace_rbug_context_draw_step(tr_rbug, header, serial); - break; - case RBUG_OP_CONTEXT_DRAW_UNBLOCK: - ret = trace_rbug_context_draw_unblock(tr_rbug, header, serial); - break; - case RBUG_OP_CONTEXT_DRAW_RULE: - ret = trace_rbug_context_draw_rule(tr_rbug, header, serial); - break; - case RBUG_OP_CONTEXT_FLUSH: - ret = trace_rbug_context_flush(tr_rbug, header, serial); - break; - case RBUG_OP_SHADER_LIST: - ret = trace_rbug_shader_list(tr_rbug, header, serial); - break; - case RBUG_OP_SHADER_INFO: - ret = trace_rbug_shader_info(tr_rbug, header, serial); - break; - case RBUG_OP_SHADER_DISABLE: - ret = trace_rbug_shader_disable(tr_rbug, header); - break; - case RBUG_OP_SHADER_REPLACE: - ret = trace_rbug_shader_replace(tr_rbug, header); - break; - default: - debug_printf("%s - unsupported opcode %u\n", __FUNCTION__, header->opcode); - ret = -ENOSYS; - break; - } - rbug_free_header(header); - - if (ret) - rbug_send_error_reply(tr_rbug->con, serial, ret, NULL); - - return TRUE; -} - -static void -trace_rbug_con(struct trace_rbug *tr_rbug) -{ - struct rbug_header *header; - uint32_t serial; - - debug_printf("%s - connection received\n", __FUNCTION__); - - while(tr_rbug->running) { - header = rbug_get_message(tr_rbug->con, &serial); - if (!header) - break; - - if (!trace_rbug_header(tr_rbug, header, serial)) - break; - } - - debug_printf("%s - connection closed\n", __FUNCTION__); - - rbug_disconnect(tr_rbug->con); - tr_rbug->con = NULL; -} - -PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug) -{ - struct trace_rbug *tr_rbug = void_tr_rbug; - uint16_t port = 13370; - int s = -1; - int c; - - u_socket_init(); - - for (;port <= 13379 && s < 0; port++) - s = u_socket_listen_on_port(port); - - if (s < 0) { - debug_printf("trace_rbug - failed to listen\n"); - return NULL; - } - - u_socket_block(s, false); - - debug_printf("trace_rbug - remote debugging listening on port %u\n", --port); - - while(tr_rbug->running) { - os_time_sleep(1); - - c = u_socket_accept(s); - if (c < 0) - continue; - - u_socket_block(c, true); - tr_rbug->con = rbug_from_socket(c); - - trace_rbug_con(tr_rbug); - - u_socket_close(c); - } - - u_socket_close(s); - - u_socket_stop(); - - return NULL; -} - -/********************************************************** - * - */ - -struct trace_rbug * -trace_rbug_start(struct trace_screen *tr_scr) -{ - struct trace_rbug *tr_rbug = CALLOC_STRUCT(trace_rbug); - if (!tr_rbug) - return NULL; - - tr_rbug->tr_scr = tr_scr; - tr_rbug->running = TRUE; - tr_rbug->thread = pipe_thread_create(trace_rbug_thread, tr_rbug); - - return tr_rbug; -} - -void -trace_rbug_stop(struct trace_rbug *tr_rbug) -{ - if (!tr_rbug) - return; - - tr_rbug->running = false; - pipe_thread_wait(tr_rbug->thread); - - FREE(tr_rbug); - - return; -} - -void -trace_rbug_notify_draw_blocked(struct trace_context *tr_ctx) -{ - struct trace_screen *tr_scr = trace_screen(tr_ctx->base.screen); - struct trace_rbug *tr_rbug = tr_scr->rbug; - - if (tr_rbug && tr_rbug->con) - rbug_send_context_draw_blocked(tr_rbug->con, - VOID2U64(tr_ctx), tr_ctx->draw_blocked, NULL); -} diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c index ffae6e94d11..32e519a68a0 100644 --- a/src/gallium/drivers/trace/tr_screen.c +++ b/src/gallium/drivers/trace/tr_screen.c @@ -40,7 +40,6 @@ static boolean trace = FALSE; -static boolean rbug = FALSE; static const char * trace_screen_get_name(struct pipe_screen *_screen) @@ -86,7 +85,7 @@ trace_screen_get_vendor(struct pipe_screen *_screen) static int trace_screen_get_param(struct pipe_screen *_screen, - int param) + enum pipe_cap param) { struct trace_screen *tr_scr = trace_screen(_screen); struct pipe_screen *screen = tr_scr->screen; @@ -109,7 +108,7 @@ trace_screen_get_param(struct pipe_screen *_screen, static float trace_screen_get_paramf(struct pipe_screen *_screen, - int param) + enum pipe_cap param) { struct trace_screen *tr_scr = trace_screen(_screen); struct pipe_screen *screen = tr_scr->screen; @@ -494,9 +493,6 @@ trace_screen_destroy(struct pipe_screen *_screen) trace_dump_call_end(); trace_dump_trace_end(); - if (tr_scr->rbug) - trace_rbug_stop(tr_scr->rbug); - screen->destroy(screen); FREE(tr_scr); @@ -518,11 +514,6 @@ trace_enabled(void) trace = TRUE; } - if (debug_get_bool_option("GALLIUM_RBUG", FALSE)) { - trace = TRUE; - rbug = TRUE; - } - return trace; } @@ -551,13 +542,6 @@ trace_screen_create(struct pipe_screen *screen) #else winsys = screen->winsys; #endif - pipe_mutex_init(tr_scr->list_mutex); - make_empty_list(&tr_scr->buffers); - make_empty_list(&tr_scr->contexts); - make_empty_list(&tr_scr->textures); - make_empty_list(&tr_scr->surfaces); - make_empty_list(&tr_scr->transfers); - tr_scr->base.winsys = winsys; tr_scr->base.destroy = trace_screen_destroy; tr_scr->base.get_name = trace_screen_get_name; @@ -580,20 +564,12 @@ trace_screen_create(struct pipe_screen *screen) tr_scr->base.flush_frontbuffer = trace_screen_flush_frontbuffer; tr_scr->screen = screen; - tr_scr->private_context = screen->context_create(screen, NULL); - if (tr_scr->private_context == NULL) - goto error3; trace_dump_ret(ptr, screen); trace_dump_call_end(); - if (rbug) - tr_scr->rbug = trace_rbug_start(tr_scr); - return &tr_scr->base; -error3: - FREE(tr_scr); error2: trace_dump_ret(ptr, screen); trace_dump_call_end(); diff --git a/src/gallium/drivers/trace/tr_screen.h b/src/gallium/drivers/trace/tr_screen.h index 05ff9ef61f1..3598ceaa20f 100644 --- a/src/gallium/drivers/trace/tr_screen.h +++ b/src/gallium/drivers/trace/tr_screen.h @@ -56,67 +56,17 @@ struct trace_screen struct pipe_screen base; struct pipe_screen *screen; - struct pipe_context *private_context; - - /* remote debugger */ - struct trace_rbug *rbug; - - pipe_mutex list_mutex; - int num_buffers; - int num_contexts; - int num_textures; - int num_surfaces; - int num_transfers; - struct tr_list buffers; - struct tr_list contexts; - struct tr_list textures; - struct tr_list surfaces; - struct tr_list transfers; }; /* - * tr_rbug.c - */ - - -struct trace_rbug; - -struct trace_rbug * -trace_rbug_start(struct trace_screen *tr_scr); - -void -trace_rbug_stop(struct trace_rbug *tr_rbug); - - -/* * tr_screen.c */ -boolean -trace_enabled(void); - struct trace_screen * trace_screen(struct pipe_screen *screen); -#define trace_screen_add_to_list(tr_scr, name, obj) \ - do { \ - pipe_mutex_lock(tr_scr->list_mutex); \ - insert_at_head(&tr_scr->name, &obj->list); \ - tr_scr->num_##name++; \ - pipe_mutex_unlock(tr_scr->list_mutex); \ - } while (0) - -#define trace_screen_remove_from_list(tr_scr, name, obj) \ - do { \ - pipe_mutex_lock(tr_scr->list_mutex); \ - remove_from_list(&obj->list); \ - tr_scr->num_##name--; \ - pipe_mutex_unlock(tr_scr->list_mutex); \ - } while (0) - - #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/trace/tr_state.c b/src/gallium/drivers/trace/tr_state.c deleted file mode 100644 index d8c11640bf3..00000000000 --- a/src/gallium/drivers/trace/tr_state.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * 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 - * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "tr_state.h" - -#include "util/u_memory.h" -#include "util/u_simple_list.h" - -#include "tgsi/tgsi_parse.h" - -struct trace_shader * trace_shader_create(struct trace_context *tr_ctx, - const struct pipe_shader_state *state, - void *result, - enum trace_shader_type type) -{ - struct trace_shader *tr_shdr = CALLOC_STRUCT(trace_shader); - - tr_shdr->state = result; - tr_shdr->type = type; - tr_shdr->tokens = tgsi_dup_tokens(state->tokens); - - /* works on context as well */ - trace_screen_add_to_list(tr_ctx, shaders, tr_shdr); - - return tr_shdr; -} - -void trace_shader_destroy(struct trace_context *tr_ctx, - struct trace_shader *tr_shdr) -{ - trace_screen_remove_from_list(tr_ctx, shaders, tr_shdr); - - if (tr_shdr->replaced) { - if (tr_shdr->type == TRACE_SHADER_FRAGMENT) - tr_ctx->pipe->delete_fs_state(tr_ctx->pipe, tr_shdr->replaced); - else if (tr_shdr->type == TRACE_SHADER_VERTEX) - tr_ctx->pipe->delete_vs_state(tr_ctx->pipe, tr_shdr->replaced); - else - assert(0); - } - - FREE(tr_shdr->replaced_tokens); - FREE(tr_shdr->tokens); - FREE(tr_shdr); -} diff --git a/src/gallium/drivers/trace/tr_state.h b/src/gallium/drivers/trace/tr_state.h deleted file mode 100644 index e2f981d0513..00000000000 --- a/src/gallium/drivers/trace/tr_state.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * 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 - * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef TR_STATE_H_ -#define TR_STATE_H_ - -#include "tr_context.h" - -struct tgsi_token; - -enum trace_shader_type { - TRACE_SHADER_FRAGMENT = 0, - TRACE_SHADER_VERTEX = 1, - TRACE_SHADER_GEOMETRY = 2 -}; - -struct trace_shader -{ - struct tr_list list; - - enum trace_shader_type type; - - void *state; - void *replaced; - - struct tgsi_token *tokens; - struct tgsi_token *replaced_tokens; - - boolean disabled; -}; - - -static INLINE struct trace_shader * -trace_shader(void *state) -{ - return (struct trace_shader *)state; -} - -struct trace_shader * trace_shader_create(struct trace_context *tr_ctx, - const struct pipe_shader_state *state, - void *result, - enum trace_shader_type type); - -void trace_shader_destroy(struct trace_context *tr_ctx, - struct trace_shader *tr_shdr); - -#endif diff --git a/src/gallium/drivers/trace/tr_texture.c b/src/gallium/drivers/trace/tr_texture.c index 1132dc92724..9914b98b39c 100644 --- a/src/gallium/drivers/trace/tr_texture.c +++ b/src/gallium/drivers/trace/tr_texture.c @@ -56,8 +56,6 @@ trace_resource_create(struct trace_screen *tr_scr, tr_tex->base.screen = &tr_scr->base; tr_tex->resource = texture; - trace_screen_add_to_list(tr_scr, textures, tr_tex); - return &tr_tex->base; error: @@ -70,8 +68,6 @@ void trace_resource_destroy(struct trace_screen *tr_scr, struct trace_resource *tr_tex) { - trace_screen_remove_from_list(tr_scr, textures, tr_tex); - pipe_resource_reference(&tr_tex->resource, NULL); FREE(tr_tex); } @@ -81,7 +77,6 @@ struct pipe_surface * trace_surface_create(struct trace_resource *tr_tex, struct pipe_surface *surface) { - struct trace_screen *tr_scr = trace_screen(tr_tex->base.screen); struct trace_surface *tr_surf; if(!surface) @@ -100,8 +95,6 @@ trace_surface_create(struct trace_resource *tr_tex, pipe_resource_reference(&tr_surf->base.texture, &tr_tex->base); tr_surf->surface = surface; - trace_screen_add_to_list(tr_scr, surfaces, tr_surf); - return &tr_surf->base; error: @@ -113,10 +106,6 @@ error: void trace_surface_destroy(struct trace_surface *tr_surf) { - struct trace_screen *tr_scr = trace_screen(tr_surf->base.texture->screen); - - trace_screen_remove_from_list(tr_scr, surfaces, tr_surf); - pipe_resource_reference(&tr_surf->base.texture, NULL); pipe_surface_reference(&tr_surf->surface, NULL); FREE(tr_surf); @@ -128,7 +117,6 @@ trace_transfer_create(struct trace_context *tr_ctx, struct trace_resource *tr_tex, struct pipe_transfer *transfer) { - struct trace_screen *tr_scr = trace_screen(tr_tex->base.screen); struct trace_transfer *tr_trans; if(!transfer) @@ -148,8 +136,6 @@ trace_transfer_create(struct trace_context *tr_ctx, pipe_resource_reference(&tr_trans->base.resource, &tr_tex->base); assert(tr_trans->base.resource == &tr_tex->base); - trace_screen_add_to_list(tr_scr, transfers, tr_trans); - return &tr_trans->base; error: @@ -162,12 +148,9 @@ void trace_transfer_destroy(struct trace_context *tr_context, struct trace_transfer *tr_trans) { - struct trace_screen *tr_scr = trace_screen(tr_context->base.screen); struct pipe_context *context = tr_context->pipe; struct pipe_transfer *transfer = tr_trans->transfer; - trace_screen_remove_from_list(tr_scr, transfers, tr_trans); - pipe_resource_reference(&tr_trans->base.resource, NULL); context->transfer_destroy(context, transfer); FREE(tr_trans); |