diff options
author | José Fonseca <jfonseca@vmware.com> | 2010-01-31 05:36:33 +0000 |
---|---|---|
committer | José Fonseca <jfonseca@vmware.com> | 2010-01-31 05:36:33 +0000 |
commit | bee9964b29b2428ee75e2d1efc0e1d2c2518a417 (patch) | |
tree | fd733f886743b31f2ac2727e57f05d1a0918a977 /src/gallium | |
parent | 36a0819ff4ede1af91dcf909106cf20659856384 (diff) | |
parent | 12eb32e34244db9923cacaaed9ba951b7ac274a4 (diff) |
Merge remote branch 'origin/master' into lp-binning
Conflicts:
Makefile
src/gallium/auxiliary/util/u_surface.c
src/gallium/drivers/llvmpipe/lp_flush.c
src/gallium/drivers/llvmpipe/lp_setup.c
src/gallium/drivers/llvmpipe/lp_state_derived.c
src/gallium/drivers/llvmpipe/lp_state_fs.c
src/gallium/drivers/llvmpipe/lp_state_surface.c
src/gallium/drivers/llvmpipe/lp_tex_cache.c
src/gallium/drivers/llvmpipe/lp_texture.c
src/gallium/drivers/llvmpipe/lp_tile_cache.c
src/mesa/state_tracker/st_cb_condrender.c
Diffstat (limited to 'src/gallium')
338 files changed, 6069 insertions, 6069 deletions
diff --git a/src/gallium/SConscript b/src/gallium/SConscript index eea32b1314..d56c5c8461 100644 --- a/src/gallium/SConscript +++ b/src/gallium/SConscript @@ -8,9 +8,10 @@ for driver in env['drivers']: SConscript(os.path.join('drivers', driver, 'SConscript')) SConscript('state_trackers/python/SConscript') -SConscript('state_trackers/glx/xlib/SConscript') -SConscript('state_trackers/dri/SConscript') -SConscript('state_trackers/xorg/SConscript') +if platform != 'embedded': + SConscript('state_trackers/glx/xlib/SConscript') + SConscript('state_trackers/dri/SConscript') + SConscript('state_trackers/xorg/SConscript') if platform == 'windows': SConscript('state_trackers/wgl/SConscript') diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index 8f937e3b4e..da1fb6b299 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -48,12 +48,10 @@ C_SOURCES = \ draw/draw_vs_sse.c \ indices/u_indices_gen.c \ indices/u_unfilled_gen.c \ - pipebuffer/pb_buffer_fenced.c \ pipebuffer/pb_buffer_malloc.c \ pipebuffer/pb_bufmgr_alt.c \ pipebuffer/pb_bufmgr_cache.c \ pipebuffer/pb_bufmgr_debug.c \ - pipebuffer/pb_bufmgr_fenced.c \ pipebuffer/pb_bufmgr_mm.c \ pipebuffer/pb_bufmgr_ondemand.c \ pipebuffer/pb_bufmgr_pool.c \ @@ -92,6 +90,7 @@ C_SOURCES = \ util/u_debug_dump.c \ util/u_debug_symbol.c \ util/u_debug_stack.c \ + util/u_bitmask.c \ util/u_blit.c \ util/u_blitter.c \ util/u_cache.c \ diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index f957090b5f..3aa782f81e 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -87,7 +87,6 @@ source = [ 'pipebuffer/pb_bufmgr_alt.c', 'pipebuffer/pb_bufmgr_cache.c', 'pipebuffer/pb_bufmgr_debug.c', - 'pipebuffer/pb_bufmgr_fenced.c', 'pipebuffer/pb_bufmgr_mm.c', 'pipebuffer/pb_bufmgr_ondemand.c', 'pipebuffer/pb_bufmgr_pool.c', diff --git a/src/gallium/auxiliary/cso_cache/cso_cache.c b/src/gallium/auxiliary/cso_cache/cso_cache.c index e6dce3f0e5..a6a07e72c2 100644 --- a/src/gallium/auxiliary/cso_cache/cso_cache.c +++ b/src/gallium/auxiliary/cso_cache/cso_cache.c @@ -113,26 +113,6 @@ static struct cso_hash *_cso_hash_for_type(struct cso_cache *sc, enum cso_cache_ return hash; } -static int _cso_size_for_type(enum cso_cache_type type) -{ - switch(type) { - case CSO_BLEND: - return sizeof(struct pipe_blend_state); - case CSO_SAMPLER: - return sizeof(struct pipe_sampler_state); - case CSO_DEPTH_STENCIL_ALPHA: - return sizeof(struct pipe_depth_stencil_alpha_state); - case CSO_RASTERIZER: - return sizeof(struct pipe_rasterizer_state); - case CSO_FRAGMENT_SHADER: - return sizeof(struct pipe_shader_state); - case CSO_VERTEX_SHADER: - return sizeof(struct pipe_shader_state); - } - return 0; -} - - static void delete_blend_state(void *state, void *data) { struct cso_blend *cso = (struct cso_blend *)state; @@ -282,10 +262,9 @@ void *cso_hash_find_data_from_template( struct cso_hash *hash, struct cso_hash_iter cso_find_state_template(struct cso_cache *sc, unsigned hash_key, enum cso_cache_type type, - void *templ) + void *templ, unsigned size) { struct cso_hash_iter iter = cso_find_state(sc, hash_key, type); - int size = _cso_size_for_type(type); while (!cso_hash_iter_is_null(iter)) { void *iter_data = cso_hash_iter_data(iter); if (!memcmp(iter_data, templ, size)) diff --git a/src/gallium/auxiliary/cso_cache/cso_cache.h b/src/gallium/auxiliary/cso_cache/cso_cache.h index 6b5c230e8f..eea60b940b 100644 --- a/src/gallium/auxiliary/cso_cache/cso_cache.h +++ b/src/gallium/auxiliary/cso_cache/cso_cache.h @@ -160,7 +160,7 @@ struct cso_hash_iter cso_find_state(struct cso_cache *sc, unsigned hash_key, enum cso_cache_type type); struct cso_hash_iter cso_find_state_template(struct cso_cache *sc, unsigned hash_key, enum cso_cache_type type, - void *templ); + void *templ, unsigned size); void cso_for_each_state(struct cso_cache *sc, enum cso_cache_type type, cso_state_callback func, void *user_data); void * cso_take_state(struct cso_cache *sc, unsigned hash_key, diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 2b16332e14..dec830ba93 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -310,18 +310,21 @@ void cso_destroy_context( struct cso_context *ctx ) enum pipe_error cso_set_blend(struct cso_context *ctx, const struct pipe_blend_state *templ) { - unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_blend_state)); - struct cso_hash_iter iter = cso_find_state_template(ctx->cache, - hash_key, CSO_BLEND, - (void*)templ); + unsigned key_size, hash_key; + struct cso_hash_iter iter; void *handle; + key_size = templ->independent_blend_enable ? sizeof(struct pipe_blend_state) : + (char *)&(templ->rt[1]) - (char *)templ; + hash_key = cso_construct_key((void*)templ, key_size); + iter = cso_find_state_template(ctx->cache, hash_key, CSO_BLEND, (void*)templ, key_size); + if (cso_hash_iter_is_null(iter)) { struct cso_blend *cso = MALLOC(sizeof(struct cso_blend)); if (!cso) return PIPE_ERROR_OUT_OF_MEMORY; - memcpy(&cso->state, templ, sizeof(*templ)); + memcpy(&cso->state, templ, key_size); cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state); cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state; cso->context = ctx->pipe; @@ -369,10 +372,11 @@ enum pipe_error cso_single_sampler(struct cso_context *ctx, void *handle = NULL; if (templ != NULL) { - unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_sampler_state)); + unsigned key_size = sizeof(struct pipe_sampler_state); + unsigned hash_key = cso_construct_key((void*)templ, key_size); struct cso_hash_iter iter = cso_find_state_template(ctx->cache, hash_key, CSO_SAMPLER, - (void*)templ); + (void*)templ, key_size); if (cso_hash_iter_is_null(iter)) { struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); @@ -409,10 +413,11 @@ cso_single_vertex_sampler(struct cso_context *ctx, void *handle = NULL; if (templ != NULL) { - unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_sampler_state)); + unsigned key_size = sizeof(struct pipe_sampler_state); + unsigned hash_key = cso_construct_key((void*)templ, key_size); struct cso_hash_iter iter = cso_find_state_template(ctx->cache, hash_key, CSO_SAMPLER, - (void*)templ); + (void*)templ, key_size); if (cso_hash_iter_is_null(iter)) { struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); @@ -539,6 +544,38 @@ void cso_restore_samplers(struct cso_context *ctx) cso_single_sampler_done( ctx ); } +/* + * If the function encouters any errors it will return the + * last one. Done to always try to set as many samplers + * as possible. + */ +enum pipe_error cso_set_vertex_samplers(struct cso_context *ctx, + unsigned nr, + const struct pipe_sampler_state **templates) +{ + unsigned i; + enum pipe_error temp, error = PIPE_OK; + + /* TODO: fastpath + */ + + for (i = 0; i < nr; i++) { + temp = cso_single_vertex_sampler( ctx, i, templates[i] ); + if (temp != PIPE_OK) + error = temp; + } + + for ( ; i < ctx->nr_samplers; i++) { + temp = cso_single_vertex_sampler( ctx, i, NULL ); + if (temp != PIPE_OK) + error = temp; + } + + cso_single_vertex_sampler_done( ctx ); + + return error; +} + void cso_save_vertex_samplers(struct cso_context *ctx) { @@ -666,12 +703,12 @@ cso_restore_vertex_sampler_textures(struct cso_context *ctx) enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx, const struct pipe_depth_stencil_alpha_state *templ) { - unsigned hash_key = cso_construct_key((void*)templ, - sizeof(struct pipe_depth_stencil_alpha_state)); + unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_state); + unsigned hash_key = cso_construct_key((void*)templ, key_size); struct cso_hash_iter iter = cso_find_state_template(ctx->cache, hash_key, - CSO_DEPTH_STENCIL_ALPHA, - (void*)templ); + CSO_DEPTH_STENCIL_ALPHA, + (void*)templ, key_size); void *handle; if (cso_hash_iter_is_null(iter)) { @@ -723,11 +760,11 @@ void cso_restore_depth_stencil_alpha(struct cso_context *ctx) enum pipe_error cso_set_rasterizer(struct cso_context *ctx, const struct pipe_rasterizer_state *templ) { - unsigned hash_key = cso_construct_key((void*)templ, - sizeof(struct pipe_rasterizer_state)); + unsigned key_size = sizeof(struct pipe_rasterizer_state); + unsigned hash_key = cso_construct_key((void*)templ, key_size); struct cso_hash_iter iter = cso_find_state_template(ctx->cache, hash_key, CSO_RASTERIZER, - (void*)templ); + (void*)templ, key_size); void *handle = NULL; if (cso_hash_iter_is_null(iter)) { @@ -809,7 +846,8 @@ enum pipe_error cso_set_fragment_shader(struct cso_context *ctx, struct cso_hash_iter iter = cso_find_state_template(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, - (void*)tokens); + (void*)tokens, + sizeof(*templ)); /* XXX correct? tokens_size? */ void *handle = NULL; if (cso_hash_iter_is_null(iter)) { @@ -888,7 +926,8 @@ enum pipe_error cso_set_vertex_shader(struct cso_context *ctx, sizeof(struct pipe_shader_state)); struct cso_hash_iter iter = cso_find_state_template(ctx->cache, hash_key, CSO_VERTEX_SHADER, - (void*)templ); + (void*)templ, + sizeof(*templ)); void *handle = NULL; if (cso_hash_iter_is_null(iter)) { diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index b9e313e32d..d2089b1c88 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -84,6 +84,10 @@ enum pipe_error cso_single_sampler( struct cso_context *cso, void cso_single_sampler_done( struct cso_context *cso ); +enum pipe_error cso_set_vertex_samplers(struct cso_context *cso, + unsigned count, + const struct pipe_sampler_state **states); + void cso_save_vertex_samplers(struct cso_context *cso); diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index e90dfc5aec..d3084fd428 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -34,11 +34,8 @@ #include "util/u_memory.h" #include "util/u_math.h" #include "draw_context.h" -#include "draw_vbuf.h" #include "draw_vs.h" #include "draw_gs.h" -#include "draw_pt.h" -#include "draw_pipe.h" struct draw_context *draw_create( void ) @@ -237,17 +234,20 @@ draw_set_mapped_vertex_buffer(struct draw_context *draw, void draw_set_mapped_constant_buffer(struct draw_context *draw, unsigned shader_type, + unsigned slot, const void *buffer, unsigned size ) { debug_assert(shader_type == PIPE_SHADER_VERTEX || shader_type == PIPE_SHADER_GEOMETRY); + debug_assert(slot < PIPE_MAX_CONSTANT_BUFFERS); + if (shader_type == PIPE_SHADER_VERTEX) { - draw->pt.user.vs_constants = buffer; - draw_vs_set_constants( draw, (const float (*)[4])buffer, size ); + draw->pt.user.vs_constants[slot] = buffer; + draw_vs_set_constants(draw, slot, buffer, size); } else if (shader_type == PIPE_SHADER_GEOMETRY) { - draw->pt.user.gs_constants = buffer; - draw_gs_set_constants( draw, (const float (*)[4])buffer, size ); + draw->pt.user.gs_constants[slot] = buffer; + draw_gs_set_constants(draw, slot, buffer, size); } } diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index 8a64c06efc..acd81b9712 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -151,10 +151,12 @@ void draw_set_mapped_element_buffer( struct draw_context *draw, void draw_set_mapped_vertex_buffer(struct draw_context *draw, unsigned attr, const void *buffer); -void draw_set_mapped_constant_buffer(struct draw_context *draw, - unsigned shader_type, - const void *buffer, - unsigned size ); +void +draw_set_mapped_constant_buffer(struct draw_context *draw, + unsigned shader_type, + unsigned slot, + const void *buffer, + unsigned size); /*********************************************************************** diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c index daf8d071f1..7069aa6b18 100644 --- a/src/gallium/auxiliary/draw/draw_gs.c +++ b/src/gallium/auxiliary/draw/draw_gs.c @@ -69,9 +69,11 @@ void draw_gs_destroy( struct draw_context *draw ) tgsi_exec_machine_destroy(draw->gs.machine); } -void draw_gs_set_constants( struct draw_context *draw, - const float (*constants)[4], - unsigned size ) +void +draw_gs_set_constants(struct draw_context *draw, + unsigned slot, + const void *constants, + unsigned size) { } @@ -291,7 +293,7 @@ draw_geometry_fetch_outputs(struct draw_geometry_shader *shader, void draw_geometry_shader_run(struct draw_geometry_shader *shader, const float (*input)[4], float (*output)[4], - const float (*constants)[4], + const void *constants[PIPE_MAX_CONSTANT_BUFFERS], unsigned count, unsigned input_stride, unsigned vertex_size) @@ -302,7 +304,9 @@ void draw_geometry_shader_run(struct draw_geometry_shader *shader, unsigned num_primitives = count/num_vertices; unsigned inputs_from_vs = 0; - machine->Consts = constants; + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + machine->Consts[i] = constants[i]; + } for (i = 0; i < shader->info.num_inputs; ++i) { if (shader->info.input_semantic_name[i] != TGSI_SEMANTIC_PRIMID) diff --git a/src/gallium/auxiliary/draw/draw_gs.h b/src/gallium/auxiliary/draw/draw_gs.h index d6a97d9c4e..d8eb210343 100644 --- a/src/gallium/auxiliary/draw/draw_gs.h +++ b/src/gallium/auxiliary/draw/draw_gs.h @@ -62,7 +62,7 @@ struct draw_geometry_shader { void draw_geometry_shader_run(struct draw_geometry_shader *shader, const float (*input)[4], float (*output)[4], - const float (*constants)[4], + const void *constants[PIPE_MAX_CONSTANT_BUFFERS], unsigned count, unsigned input_stride, unsigned output_stride); diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c index 1c6d657297..11d6485dcf 100644 --- a/src/gallium/auxiliary/draw/draw_pipe.c +++ b/src/gallium/auxiliary/draw/draw_pipe.c @@ -106,10 +106,9 @@ void draw_pipeline_destroy( struct draw_context *draw ) - - - - +/** + * Build primitive to render a point with vertex at v0. + */ static void do_point( struct draw_context *draw, const char *v0 ) { @@ -123,6 +122,10 @@ static void do_point( struct draw_context *draw, } +/** + * Build primitive to render a line with vertices at v0, v1. + * \param flags bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE + */ static void do_line( struct draw_context *draw, ushort flags, const char *v0, @@ -139,6 +142,10 @@ static void do_line( struct draw_context *draw, } +/** + * Build primitive to render a triangle with vertices at v0, v1, v2. + * \param flags bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE + */ static void do_triangle( struct draw_context *draw, ushort flags, char *v0, @@ -157,7 +164,10 @@ static void do_triangle( struct draw_context *draw, } - +/* + * Set up macros for draw_pt_decompose.h template code. + * This code uses vertex indexes / elements. + */ #define QUAD(i0,i1,i2,i3) \ do_triangle( draw, \ ( DRAW_PIPE_RESET_STIPPLE | \ @@ -175,16 +185,16 @@ static void do_triangle( struct draw_context *draw, #define TRIANGLE(flags,i0,i1,i2) \ do_triangle( draw, \ - elts[i0], /* flags */ \ + elts[i0], /* flags */ \ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \ - verts + stride * elts[i1], \ - verts + stride * elts[i2]) + verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK) ); #define LINE(flags,i0,i1) \ do_line( draw, \ - elts[i0], \ + elts[i0], \ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \ - verts + stride * elts[i1]) + verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK) ); #define POINT(i0) \ do_point( draw, \ @@ -213,7 +223,9 @@ static void do_triangle( struct draw_context *draw, -/* Code to run the pipeline on a fairly arbitary collection of vertices. +/** + * Code to run the pipeline on a fairly arbitary collection of vertices. + * For drawing indexed primitives. * * Vertex headers must be pre-initialized with the * UNDEFINED_VERTEX_ID, this code will cause that id to become @@ -243,6 +255,12 @@ void draw_pipeline_run( struct draw_context *draw, draw->pipeline.vertex_count = 0; } + + +/* + * Set up macros for draw_pt_decompose.h template code. + * This code is for non-indexed rendering (no elts). + */ #define QUAD(i0,i1,i2,i3) \ do_triangle( draw, \ ( DRAW_PIPE_RESET_STIPPLE | \ @@ -293,6 +311,10 @@ void draw_pipeline_run( struct draw_context *draw, #include "draw_pt_decompose.h" + +/* + * For drawing non-indexed primitives. + */ void draw_pipeline_run_linear( struct draw_context *draw, unsigned prim, struct vertex_header *vertices, diff --git a/src/gallium/auxiliary/draw/draw_pipe_cull.c b/src/gallium/auxiliary/draw/draw_pipe_cull.c index 11b39db599..dc66c65a56 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_cull.c +++ b/src/gallium/auxiliary/draw/draw_pipe_cull.c @@ -50,8 +50,6 @@ static INLINE struct cull_stage *cull_stage( struct draw_stage *stage ) } - - static void cull_tri( struct draw_stage *stage, struct prim_header *header ) { @@ -62,7 +60,7 @@ static void cull_tri( struct draw_stage *stage, const float *v1 = header->v[1]->data[pos]; const float *v2 = header->v[2]->data[pos]; - /* edge vectors e = v0 - v2, f = v1 - v2 */ + /* edge vectors: e = v0 - v2, f = v1 - v2 */ const float ex = v0[0] - v2[0]; const float ey = v0[1] - v2[1]; const float fx = v1[0] - v2[0]; @@ -72,7 +70,7 @@ static void cull_tri( struct draw_stage *stage, header->det = ex * fy - ey * fx; if (header->det != 0) { - /* if (det < 0 then Z points toward camera and triangle is + /* if det < 0 then Z points toward the camera and the triangle is * counter-clockwise winding. */ unsigned winding = (header->det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW; @@ -84,6 +82,7 @@ static void cull_tri( struct draw_stage *stage, } } + static void cull_first_tri( struct draw_stage *stage, struct prim_header *header ) { @@ -96,13 +95,13 @@ static void cull_first_tri( struct draw_stage *stage, } - static void cull_flush( struct draw_stage *stage, unsigned flags ) { stage->tri = cull_first_tri; stage->next->flush( stage->next, flags ); } + static void cull_reset_stipple_counter( struct draw_stage *stage ) { stage->next->reset_stipple_counter( stage->next ); @@ -140,7 +139,7 @@ struct draw_stage *draw_cull_stage( struct draw_context *draw ) return &cull->stage; - fail: +fail: if (cull) cull->stage.destroy( &cull->stage ); diff --git a/src/gallium/auxiliary/draw/draw_pipe_validate.c b/src/gallium/auxiliary/draw/draw_pipe_validate.c index bea90e50d3..a69e2633be 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_validate.c +++ b/src/gallium/auxiliary/draw/draw_pipe_validate.c @@ -151,8 +151,8 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage ) { struct draw_context *draw = stage->draw; struct draw_stage *next = draw->pipeline.rasterize; - int need_det = 0; - int precalc_flat = 0; + boolean need_det = FALSE; + boolean precalc_flat = FALSE; boolean wide_lines, wide_points; /* Set the validate's next stage to the rasterize stage, so that it @@ -194,7 +194,7 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage ) if (wide_lines) { draw->pipeline.wide_line->next = next; next = draw->pipeline.wide_line; - precalc_flat = 1; + precalc_flat = TRUE; } if (wide_points || draw->rasterizer->point_sprite) { @@ -205,7 +205,7 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage ) if (draw->rasterizer->line_stipple_enable && draw->pipeline.line_stipple) { draw->pipeline.stipple->next = next; next = draw->pipeline.stipple; - precalc_flat = 1; /* only needed for lines really */ + precalc_flat = TRUE; /* only needed for lines really */ } if (draw->rasterizer->poly_stipple_enable @@ -218,8 +218,8 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage ) draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) { draw->pipeline.unfilled->next = next; next = draw->pipeline.unfilled; - precalc_flat = 1; /* only needed for triangles really */ - need_det = 1; + precalc_flat = TRUE; /* only needed for triangles really */ + need_det = TRUE; } if (draw->rasterizer->flatshade && precalc_flat) { @@ -231,13 +231,13 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage ) draw->rasterizer->offset_ccw) { draw->pipeline.offset->next = next; next = draw->pipeline.offset; - need_det = 1; + need_det = TRUE; } if (draw->rasterizer->light_twoside) { draw->pipeline.twoside->next = next; next = draw->pipeline.twoside; - need_det = 1; + need_det = TRUE; } /* Always run the cull stage as we calculate determinant there diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index ef49e57536..6a7190e975 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -153,8 +153,8 @@ struct draw_context const void *vbuffer[PIPE_MAX_ATTRIBS]; /** constant buffer (for vertex/geometry shader) */ - const void *vs_constants; - const void *gs_constants; + const void *vs_constants[PIPE_MAX_CONSTANT_BUFFERS]; + const void *gs_constants[PIPE_MAX_CONSTANT_BUFFERS]; } user; boolean test_fse; /* enable FSE even though its not correct (eg for softpipe) */ @@ -202,10 +202,10 @@ struct draw_context struct aos_machine *aos_machine; - const float (*aligned_constants)[4]; + const void *aligned_constants[PIPE_MAX_CONSTANT_BUFFERS]; - const float (*aligned_constant_storage)[4]; - unsigned const_storage_size; + const void *aligned_constant_storage[PIPE_MAX_CONSTANT_BUFFERS]; + unsigned const_storage_size[PIPE_MAX_CONSTANT_BUFFERS]; struct translate *fetch; @@ -256,9 +256,11 @@ void draw_vs_destroy( struct draw_context *draw ); void draw_vs_set_viewport( struct draw_context *, const struct pipe_viewport_state * ); -void draw_vs_set_constants( struct draw_context *, - const float (*constants)[4], - unsigned size ); +void +draw_vs_set_constants(struct draw_context *, + unsigned slot, + const void *constants, + unsigned size); @@ -266,9 +268,13 @@ void draw_vs_set_constants( struct draw_context *, * Geometry shading code: */ boolean draw_gs_init( struct draw_context *draw ); -void draw_gs_set_constants( struct draw_context *, - const float (*constants)[4], - unsigned size ); + +void +draw_gs_set_constants(struct draw_context *, + unsigned slot, + const void *constants, + unsigned size); + void draw_gs_destroy( struct draw_context *draw ); /******************************************************************************* diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index a5ddec5286..f5ed32d0b0 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -33,7 +33,6 @@ #include "draw/draw_context.h" #include "draw/draw_private.h" #include "draw/draw_pt.h" -#include "draw/draw_vs.h" #include "tgsi/tgsi_dump.h" #include "util/u_math.h" #include "util/u_prim.h" diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c index 55e7a7b81a..252be5053e 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c @@ -30,7 +30,6 @@ #include "draw/draw_context.h" #include "draw/draw_private.h" #include "draw/draw_vbuf.h" -#include "draw/draw_vertex.h" #include "draw/draw_pt.h" #include "translate/translate.h" #include "translate/translate_cache.h" diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c index 734c05f068..c5dfbcfa3c 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c @@ -40,7 +40,6 @@ #include "draw/draw_pt.h" #include "draw/draw_vs.h" -#include "translate/translate.h" struct fetch_shade_emit; diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c index 23da556f79..56b69354b2 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c @@ -33,7 +33,6 @@ #include "draw/draw_pt.h" #include "draw/draw_vs.h" #include "draw/draw_gs.h" -#include "translate/translate.h" struct fetch_pipeline_middle_end { @@ -164,7 +163,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle, vshader->run_linear(vshader, (const float (*)[4])pipeline_verts->data, ( float (*)[4])pipeline_verts->data, - (const float (*)[4])draw->pt.user.vs_constants, + draw->pt.user.vs_constants, fetch_count, fpme->vertex_size, fpme->vertex_size); @@ -172,7 +171,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle, draw_geometry_shader_run(gshader, (const float (*)[4])pipeline_verts->data, ( float (*)[4])pipeline_verts->data, - (const float (*)[4])draw->pt.user.gs_constants, + draw->pt.user.gs_constants, fetch_count, fpme->vertex_size, fpme->vertex_size); @@ -249,7 +248,7 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle, shader->run_linear(shader, (const float (*)[4])pipeline_verts->data, ( float (*)[4])pipeline_verts->data, - (const float (*)[4])draw->pt.user.vs_constants, + draw->pt.user.vs_constants, count, fpme->vertex_size, fpme->vertex_size); @@ -258,7 +257,7 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle, draw_geometry_shader_run(geometry_shader, (const float (*)[4])pipeline_verts->data, ( float (*)[4])pipeline_verts->data, - (const float (*)[4])draw->pt.user.gs_constants, + draw->pt.user.gs_constants, count, fpme->vertex_size, fpme->vertex_size); @@ -329,7 +328,7 @@ static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle shader->run_linear(shader, (const float (*)[4])pipeline_verts->data, ( float (*)[4])pipeline_verts->data, - (const float (*)[4])draw->pt.user.vs_constants, + draw->pt.user.vs_constants, count, fpme->vertex_size, fpme->vertex_size); @@ -338,7 +337,7 @@ static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle draw_geometry_shader_run(geometry_shader, (const float (*)[4])pipeline_verts->data, ( float (*)[4])pipeline_verts->data, - (const float (*)[4])draw->pt.user.gs_constants, + draw->pt.user.gs_constants, count, fpme->vertex_size, fpme->vertex_size); diff --git a/src/gallium/auxiliary/draw/draw_pt_post_vs.c b/src/gallium/auxiliary/draw/draw_pt_post_vs.c index 55151823a1..9728d5c2bd 100644 --- a/src/gallium/auxiliary/draw/draw_pt_post_vs.c +++ b/src/gallium/auxiliary/draw/draw_pt_post_vs.c @@ -30,7 +30,6 @@ #include "draw/draw_context.h" #include "draw/draw_private.h" #include "draw/draw_vbuf.h" -#include "draw/draw_vertex.h" #include "draw/draw_pt.h" struct pt_post_vs { diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c index e03ac8c229..6bdd612e6f 100644 --- a/src/gallium/auxiliary/draw/draw_vs.c +++ b/src/gallium/auxiliary/draw/draw_vs.c @@ -48,24 +48,27 @@ -void draw_vs_set_constants( struct draw_context *draw, - const float (*constants)[4], - unsigned size ) +void +draw_vs_set_constants(struct draw_context *draw, + unsigned slot, + const void *constants, + unsigned size) { if (((uintptr_t)constants) & 0xf) { - if (size > draw->vs.const_storage_size) { - if (draw->vs.aligned_constant_storage) - align_free((void *)draw->vs.aligned_constant_storage); - draw->vs.aligned_constant_storage = align_malloc( size, 16 ); + if (size > draw->vs.const_storage_size[slot]) { + if (draw->vs.aligned_constant_storage[slot]) { + align_free((void *)draw->vs.aligned_constant_storage[slot]); + } + draw->vs.aligned_constant_storage[slot] = align_malloc(size, 16); } - memcpy( (void*)draw->vs.aligned_constant_storage, - constants, - size ); - constants = draw->vs.aligned_constant_storage; + memcpy((void *)draw->vs.aligned_constant_storage[slot], + constants, + size); + constants = draw->vs.aligned_constant_storage[slot]; } - - draw->vs.aligned_constants = constants; - draw_vs_aos_machine_constants( draw->vs.aos_machine, constants ); + + draw->vs.aligned_constants[slot] = constants; + draw_vs_aos_machine_constants(draw->vs.aos_machine, slot, constants); } @@ -182,6 +185,8 @@ draw_vs_init( struct draw_context *draw ) void draw_vs_destroy( struct draw_context *draw ) { + uint i; + if (draw->vs.fetch_cache) translate_cache_destroy(draw->vs.fetch_cache); @@ -191,8 +196,11 @@ draw_vs_destroy( struct draw_context *draw ) if (draw->vs.aos_machine) draw_vs_aos_machine_destroy(draw->vs.aos_machine); - if (draw->vs.aligned_constant_storage) - align_free((void*)draw->vs.aligned_constant_storage); + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + if (draw->vs.aligned_constant_storage[i]) { + align_free((void *)draw->vs.aligned_constant_storage[i]); + } + } tgsi_exec_machine_destroy(draw->vs.machine); } diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h index 00036cfe68..d095c9bad1 100644 --- a/src/gallium/auxiliary/draw/draw_vs.h +++ b/src/gallium/auxiliary/draw/draw_vs.h @@ -132,7 +132,7 @@ struct draw_vertex_shader { void (*run_linear)( struct draw_vertex_shader *shader, const float (*input)[4], float (*output)[4], - const float (*constants)[4], + const void *constants[PIPE_MAX_CONSTANT_BUFFERS], unsigned count, unsigned input_stride, unsigned output_stride ); @@ -212,8 +212,10 @@ static INLINE int draw_vs_varient_key_compare( const struct draw_vs_varient_key struct aos_machine *draw_vs_aos_machine( void ); void draw_vs_aos_machine_destroy( struct aos_machine *machine ); -void draw_vs_aos_machine_constants( struct aos_machine *machine, - const float (*constants)[4] ); +void +draw_vs_aos_machine_constants(struct aos_machine *machine, + unsigned slot, + const void *constants); void draw_vs_aos_machine_viewport( struct aos_machine *machine, const struct pipe_viewport_state *viewport ); diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.c b/src/gallium/auxiliary/draw/draw_vs_aos.c index 1aaae4ab7a..e7121f3654 100644 --- a/src/gallium/auxiliary/draw/draw_vs_aos.c +++ b/src/gallium/auxiliary/draw/draw_vs_aos.c @@ -2114,11 +2114,14 @@ static void PIPE_CDECL vaos_run_elts( struct draw_vs_varient *varient, { struct draw_vs_varient_aos_sse *vaos = (struct draw_vs_varient_aos_sse *)varient; struct aos_machine *machine = vaos->draw->vs.aos_machine; + unsigned i; if (0) debug_printf("%s %d\n", __FUNCTION__, count); machine->internal[IMM_PSIZE][0] = vaos->draw->rasterizer->point_size; - machine->constants = vaos->draw->vs.aligned_constants; + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + machine->constants[i] = vaos->draw->vs.aligned_constants[i]; + } machine->immediates = vaos->base.vs->immediates; machine->buffer = vaos->buffer; @@ -2135,12 +2138,15 @@ static void PIPE_CDECL vaos_run_linear( struct draw_vs_varient *varient, { struct draw_vs_varient_aos_sse *vaos = (struct draw_vs_varient_aos_sse *)varient; struct aos_machine *machine = vaos->draw->vs.aos_machine; + unsigned i; if (0) debug_printf("%s %d %d const: %x\n", __FUNCTION__, start, count, vaos->base.key.const_vbuffers); machine->internal[IMM_PSIZE][0] = vaos->draw->rasterizer->point_size; - machine->constants = vaos->draw->vs.aligned_constants; + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + machine->constants[i] = vaos->draw->vs.aligned_constants[i]; + } machine->immediates = vaos->base.vs->immediates; machine->buffer = vaos->buffer; diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.h b/src/gallium/auxiliary/draw/draw_vs_aos.h index 2cf72ddf7b..1911242f82 100644 --- a/src/gallium/auxiliary/draw/draw_vs_aos.h +++ b/src/gallium/auxiliary/draw/draw_vs_aos.h @@ -122,7 +122,7 @@ struct aos_machine { ushort fpucntl; /* one of FPU_* above */ const float (*immediates)[4]; /* points to shader data */ - const float (*constants)[4]; /* points to draw data */ + const void *constants[PIPE_MAX_CONSTANT_BUFFERS]; /* points to draw data */ const struct aos_buffer *buffer; /* points to ? */ }; diff --git a/src/gallium/auxiliary/draw/draw_vs_aos_machine.c b/src/gallium/auxiliary/draw/draw_vs_aos_machine.c index 3240e3745d..0eda414ee6 100644 --- a/src/gallium/auxiliary/draw/draw_vs_aos_machine.c +++ b/src/gallium/auxiliary/draw/draw_vs_aos_machine.c @@ -219,10 +219,12 @@ static void PIPE_CDECL populate_lut( struct aos_machine *machine, } -void draw_vs_aos_machine_constants( struct aos_machine *machine, - const float (*constants)[4] ) +void +draw_vs_aos_machine_constants(struct aos_machine *machine, + unsigned slot, + const void *constants) { - machine->constants = constants; + machine->constants[slot] = constants; { unsigned i; @@ -307,8 +309,10 @@ void draw_vs_aos_machine_viewport( struct aos_machine *machine, { } -void draw_vs_aos_machine_constants( struct aos_machine *machine, - const float (*constants)[4] ) +void +draw_vs_aos_machine_constants(struct aos_machine *machine, + unsigned slot, + const void *constants) { } diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c index 41cc802613..7deca2b69d 100644 --- a/src/gallium/auxiliary/draw/draw_vs_exec.c +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c @@ -85,7 +85,7 @@ static void vs_exec_run_linear( struct draw_vertex_shader *shader, const float (*input)[4], float (*output)[4], - const float (*constants)[4], + const void *constants[PIPE_MAX_CONSTANT_BUFFERS], unsigned count, unsigned input_stride, unsigned output_stride ) @@ -95,7 +95,9 @@ vs_exec_run_linear( struct draw_vertex_shader *shader, unsigned int i, j; unsigned slot; - machine->Consts = constants; + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + machine->Consts[i] = constants[i]; + } for (i = 0; i < count; i += MAX_TGSI_VERTICES) { unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i); diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c index b3535c0e48..fd9166fda5 100644 --- a/src/gallium/auxiliary/draw/draw_vs_llvm.c +++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c @@ -64,7 +64,7 @@ static void vs_llvm_run_linear( struct draw_vertex_shader *base, const float (*input)[4], float (*output)[4], - const float (*constants)[4], + const void *constants[PIPE_MAX_CONSTANT_BUFFERS], unsigned count, unsigned input_stride, unsigned output_stride ) @@ -74,7 +74,8 @@ vs_llvm_run_linear( struct draw_vertex_shader *base, gallivm_cpu_vs_exec(shader->llvm_prog, shader->machine, input, base->info.num_inputs, output, base->info.num_outputs, - constants, count, input_stride, output_stride); + (const float (*)[4])constants[0], + count, input_stride, output_stride); } diff --git a/src/gallium/auxiliary/draw/draw_vs_ppc.c b/src/gallium/auxiliary/draw/draw_vs_ppc.c index da9f3e3d35..d869eecec5 100644 --- a/src/gallium/auxiliary/draw/draw_vs_ppc.c +++ b/src/gallium/auxiliary/draw/draw_vs_ppc.c @@ -85,7 +85,7 @@ static void vs_ppc_run_linear( struct draw_vertex_shader *base, const float (*input)[4], float (*output)[4], - const float (*constants)[4], + const void *constants[PIPE_MAX_CONSTANT_BUFFERS], unsigned count, unsigned input_stride, unsigned output_stride ) @@ -125,7 +125,7 @@ vs_ppc_run_linear( struct draw_vertex_shader *base, */ shader->func(inputs_soa, outputs_soa, temps_soa, (float (*)[4]) shader->base.immediates, - (float (*)[4]) constants, + (const float (*)[4])constants[0], ppc_builtin_constants); /* convert (up to) four output verts from SoA back to AoS format */ diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c index 702051387a..54e6423388 100644 --- a/src/gallium/auxiliary/draw/draw_vs_sse.c +++ b/src/gallium/auxiliary/draw/draw_vs_sse.c @@ -83,7 +83,7 @@ static void vs_sse_run_linear( struct draw_vertex_shader *base, const float (*input)[4], float (*output)[4], - const float (*constants)[4], + const void *constants[PIPE_MAX_CONSTANT_BUFFERS], unsigned count, unsigned input_stride, unsigned output_stride ) @@ -112,7 +112,7 @@ vs_sse_run_linear( struct draw_vertex_shader *base, /* run compiled shader */ shader->func(machine, - constants, + (const float (*)[4])constants[0], shader->base.immediates, input, base->info.num_inputs, diff --git a/src/gallium/auxiliary/draw/draw_vs_varient.c b/src/gallium/auxiliary/draw/draw_vs_varient.c index 9f40030f39..5ed706cb4f 100644 --- a/src/gallium/auxiliary/draw/draw_vs_varient.c +++ b/src/gallium/auxiliary/draw/draw_vs_varient.c @@ -38,7 +38,6 @@ #include "draw/draw_vertex.h" #include "draw/draw_vs.h" #include "translate/translate.h" -#include "translate/translate_cache.h" /* A first pass at incorporating vertex fetch/emit functionality into */ @@ -148,7 +147,7 @@ static void PIPE_CDECL vsvg_run_elts( struct draw_vs_varient *varient, vsvg->base.vs->run_linear( vsvg->base.vs, temp_buffer, temp_buffer, - (const float (*)[4])vsvg->base.vs->draw->pt.user.vs_constants, + vsvg->base.vs->draw->pt.user.vs_constants, count, temp_vertex_stride, temp_vertex_stride); @@ -211,7 +210,7 @@ static void PIPE_CDECL vsvg_run_linear( struct draw_vs_varient *varient, vsvg->base.vs->run_linear( vsvg->base.vs, temp_buffer, temp_buffer, - (const float (*)[4])vsvg->base.vs->draw->pt.user.vs_constants, + vsvg->base.vs->draw->pt.user.vs_constants, count, temp_vertex_stride, temp_vertex_stride); diff --git a/src/gallium/auxiliary/pipebuffer/Makefile b/src/gallium/auxiliary/pipebuffer/Makefile new file mode 100644 index 0000000000..21d25d2474 --- /dev/null +++ b/src/gallium/auxiliary/pipebuffer/Makefile @@ -0,0 +1,18 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = pipebuffer + +C_SOURCES = \ + pb_buffer_fenced.c \ + pb_buffer_malloc.c \ + pb_bufmgr_alt.c \ + pb_bufmgr_cache.c \ + pb_bufmgr_debug.c \ + pb_bufmgr_mm.c \ + pb_bufmgr_ondemand.c \ + pb_bufmgr_pool.c \ + pb_bufmgr_slab.c \ + pb_validate.c + +include ../../Makefile.template diff --git a/src/gallium/auxiliary/pipebuffer/SConscript b/src/gallium/auxiliary/pipebuffer/SConscript new file mode 100644 index 0000000000..a074a55471 --- /dev/null +++ b/src/gallium/auxiliary/pipebuffer/SConscript @@ -0,0 +1,18 @@ +Import('*') + +pipebuffer = env.ConvenienceLibrary( + target = 'pipebuffer', + source = [ + 'pb_buffer_fenced.c', + 'pb_buffer_malloc.c', + 'pb_bufmgr_alt.c', + 'pb_bufmgr_cache.c', + 'pb_bufmgr_debug.c', + 'pb_bufmgr_mm.c', + 'pb_bufmgr_ondemand.c', + 'pb_bufmgr_pool.c', + 'pb_bufmgr_slab.c', + 'pb_validate.c', + ]) + +auxiliaries.insert(0, pipebuffer) diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c index a4b78f1494..ba087ac0f3 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2007-2009 VMware, Inc. + * Copyright 2007-2010 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -28,9 +28,9 @@ /** * \file * Implementation of fenced buffers. - * - * \author Jose Fonseca <jrfonseca-at-tungstengraphics-dot-com> - * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com> + * + * \author Jose Fonseca <jfonseca-at-vmware-dot-com> + * \author Thomas Hellström <thellstrom-at-vmware-dot-com> */ @@ -50,6 +50,7 @@ #include "pb_buffer.h" #include "pb_buffer_fenced.h" +#include "pb_bufmgr.h" @@ -59,32 +60,79 @@ #define SUPER(__derived) (&(__derived)->base) -struct fenced_buffer_list +struct fenced_manager { - pipe_mutex mutex; - + struct pb_manager base; + struct pb_manager *provider; struct pb_fence_ops *ops; - - pb_size numDelayed; - struct list_head delayed; - -#ifdef DEBUG - pb_size numUnfenced; + + /** + * Maximum buffer size that can be safely allocated. + */ + pb_size max_buffer_size; + + /** + * Maximum cpu memory we can allocate before we start waiting for the + * GPU to idle. + */ + pb_size max_cpu_total_size; + + /** + * Following members are mutable and protected by this mutex. + */ + pipe_mutex mutex; + + /** + * Fenced buffer list. + * + * All fenced buffers are placed in this listed, ordered from the oldest + * fence to the newest fence. + */ + struct list_head fenced; + pb_size num_fenced; + struct list_head unfenced; -#endif + pb_size num_unfenced; + + /** + * How much temporary CPU memory is being used to hold unvalidated buffers. + */ + pb_size cpu_total_size; }; /** + * Fenced buffer. + * * Wrapper around a pipe buffer which adds fencing and reference counting. */ struct fenced_buffer { + /* + * Immutable members. + */ + struct pb_buffer base; - + struct fenced_manager *mgr; + + /* + * Following members are mutable and protected by fenced_manager::mutex. + */ + + struct list_head head; + + /** + * Buffer with storage. + */ struct pb_buffer *buffer; + pb_size size; + struct pb_desc desc; - /* FIXME: protect access with mutex */ + /** + * Temporary CPU storage data. Used when there isn't enough GPU memory to + * store the buffer. + */ + void *data; /** * A bitmask of PIPE_BUFFER_USAGE_CPU/GPU_READ/WRITE describing the current @@ -93,15 +141,22 @@ struct fenced_buffer unsigned flags; unsigned mapcount; + struct pb_validate *vl; unsigned validation_flags; - struct pipe_fence_handle *fence; - struct list_head head; - struct fenced_buffer_list *list; + struct pipe_fence_handle *fence; }; +static INLINE struct fenced_manager * +fenced_manager(struct pb_manager *mgr) +{ + assert(mgr); + return (struct fenced_manager *)mgr; +} + + static INLINE struct fenced_buffer * fenced_buffer(struct pb_buffer *buf) { @@ -110,221 +165,568 @@ fenced_buffer(struct pb_buffer *buf) } -static INLINE void -_fenced_buffer_add(struct fenced_buffer *fenced_buf) -{ - struct fenced_buffer_list *fenced_list = fenced_buf->list; +static void +fenced_buffer_destroy_cpu_storage_locked(struct fenced_buffer *fenced_buf); - assert(pipe_is_referenced(&fenced_buf->base.base.reference)); - assert(fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); - assert(fenced_buf->fence); +static enum pipe_error +fenced_buffer_create_cpu_storage_locked(struct fenced_manager *fenced_mgr, + struct fenced_buffer *fenced_buf); +static void +fenced_buffer_destroy_gpu_storage_locked(struct fenced_buffer *fenced_buf); + +static enum pipe_error +fenced_buffer_create_gpu_storage_locked(struct fenced_manager *fenced_mgr, + struct fenced_buffer *fenced_buf, + boolean wait); + +static enum pipe_error +fenced_buffer_copy_storage_to_gpu_locked(struct fenced_buffer *fenced_buf); + +static enum pipe_error +fenced_buffer_copy_storage_to_cpu_locked(struct fenced_buffer *fenced_buf); + + +/** + * Dump the fenced buffer list. + * + * Useful to understand failures to allocate buffers. + */ +static void +fenced_manager_dump_locked(struct fenced_manager *fenced_mgr) +{ #ifdef DEBUG - LIST_DEL(&fenced_buf->head); - assert(fenced_list->numUnfenced); - --fenced_list->numUnfenced; + struct pb_fence_ops *ops = fenced_mgr->ops; + struct list_head *curr, *next; + struct fenced_buffer *fenced_buf; + + debug_printf("%10s %7s %8s %7s %10s %s\n", + "buffer", "size", "refcount", "storage", "fence", "signalled"); + + curr = fenced_mgr->unfenced.next; + next = curr->next; + while(curr != &fenced_mgr->unfenced) { + fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); + assert(!fenced_buf->fence); + debug_printf("%10p %7u %8u %7s\n", + (void *) fenced_buf, + fenced_buf->base.base.size, + p_atomic_read(&fenced_buf->base.base.reference.count), + fenced_buf->buffer ? "gpu" : (fenced_buf->data ? "cpu" : "none")); + curr = next; + next = curr->next; + } + + curr = fenced_mgr->fenced.next; + next = curr->next; + while(curr != &fenced_mgr->fenced) { + int signaled; + fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); + assert(fenced_buf->buffer); + signaled = ops->fence_signalled(ops, fenced_buf->fence, 0); + debug_printf("%10p %7u %8u %7s %10p %s\n", + (void *) fenced_buf, + fenced_buf->base.base.size, + p_atomic_read(&fenced_buf->base.base.reference.count), + "gpu", + (void *) fenced_buf->fence, + signaled == 0 ? "y" : "n"); + curr = next; + next = curr->next; + } +#else + (void)fenced_mgr; #endif - LIST_ADDTAIL(&fenced_buf->head, &fenced_list->delayed); - ++fenced_list->numDelayed; } -/** - * Actually destroy the buffer. - */ static INLINE void -_fenced_buffer_destroy(struct fenced_buffer *fenced_buf) +fenced_buffer_destroy_locked(struct fenced_manager *fenced_mgr, + struct fenced_buffer *fenced_buf) { - struct fenced_buffer_list *fenced_list = fenced_buf->list; - assert(!pipe_is_referenced(&fenced_buf->base.base.reference)); + assert(!fenced_buf->fence); -#ifdef DEBUG assert(fenced_buf->head.prev); assert(fenced_buf->head.next); LIST_DEL(&fenced_buf->head); - assert(fenced_list->numUnfenced); - --fenced_list->numUnfenced; -#else - (void)fenced_list; -#endif - pb_reference(&fenced_buf->buffer, NULL); + assert(fenced_mgr->num_unfenced); + --fenced_mgr->num_unfenced; + + fenced_buffer_destroy_gpu_storage_locked(fenced_buf); + fenced_buffer_destroy_cpu_storage_locked(fenced_buf); + FREE(fenced_buf); } +/** + * Add the buffer to the fenced list. + * + * Reference count should be incremented before calling this function. + */ static INLINE void -_fenced_buffer_remove(struct fenced_buffer_list *fenced_list, - struct fenced_buffer *fenced_buf) +fenced_buffer_add_locked(struct fenced_manager *fenced_mgr, + struct fenced_buffer *fenced_buf) +{ + assert(pipe_is_referenced(&fenced_buf->base.base.reference)); + assert(fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); + assert(fenced_buf->fence); + + p_atomic_inc(&fenced_buf->base.base.reference.count); + + LIST_DEL(&fenced_buf->head); + assert(fenced_mgr->num_unfenced); + --fenced_mgr->num_unfenced; + LIST_ADDTAIL(&fenced_buf->head, &fenced_mgr->fenced); + ++fenced_mgr->num_fenced; +} + + +/** + * Remove the buffer from the fenced list, and potentially destroy the buffer + * if the reference count reaches zero. + * + * Returns TRUE if the buffer was detroyed. + */ +static INLINE boolean +fenced_buffer_remove_locked(struct fenced_manager *fenced_mgr, + struct fenced_buffer *fenced_buf) { - struct pb_fence_ops *ops = fenced_list->ops; + struct pb_fence_ops *ops = fenced_mgr->ops; assert(fenced_buf->fence); - assert(fenced_buf->list == fenced_list); - + assert(fenced_buf->mgr == fenced_mgr); + ops->fence_reference(ops, &fenced_buf->fence, NULL); fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE; - + assert(fenced_buf->head.prev); assert(fenced_buf->head.next); - + LIST_DEL(&fenced_buf->head); - assert(fenced_list->numDelayed); - --fenced_list->numDelayed; - -#ifdef DEBUG - LIST_ADDTAIL(&fenced_buf->head, &fenced_list->unfenced); - ++fenced_list->numUnfenced; -#endif - - /** - * FIXME!!! - */ + assert(fenced_mgr->num_fenced); + --fenced_mgr->num_fenced; + + LIST_ADDTAIL(&fenced_buf->head, &fenced_mgr->unfenced); + ++fenced_mgr->num_unfenced; + + if (p_atomic_dec_zero(&fenced_buf->base.base.reference.count)) { + fenced_buffer_destroy_locked(fenced_mgr, fenced_buf); + return TRUE; + } - if(!pipe_is_referenced(&fenced_buf->base.base.reference)) - _fenced_buffer_destroy(fenced_buf); + return FALSE; } +/** + * Wait for the fence to expire, and remove it from the fenced list. + * + * This function will release and re-aquire the mutex, so any copy of mutable + * state must be discarded after calling it. + */ static INLINE enum pipe_error -_fenced_buffer_finish(struct fenced_buffer *fenced_buf) +fenced_buffer_finish_locked(struct fenced_manager *fenced_mgr, + struct fenced_buffer *fenced_buf) { - struct fenced_buffer_list *fenced_list = fenced_buf->list; - struct pb_fence_ops *ops = fenced_list->ops; + struct pb_fence_ops *ops = fenced_mgr->ops; + enum pipe_error ret = PIPE_ERROR; #if 0 debug_warning("waiting for GPU"); #endif + assert(pipe_is_referenced(&fenced_buf->base.base.reference)); assert(fenced_buf->fence); + if(fenced_buf->fence) { - if(ops->fence_finish(ops, fenced_buf->fence, 0) != 0) { - return PIPE_ERROR; + struct pipe_fence_handle *fence = NULL; + int finished; + boolean proceed; + + ops->fence_reference(ops, &fence, fenced_buf->fence); + + pipe_mutex_unlock(fenced_mgr->mutex); + + finished = ops->fence_finish(ops, fenced_buf->fence, 0); + + pipe_mutex_lock(fenced_mgr->mutex); + + assert(pipe_is_referenced(&fenced_buf->base.base.reference)); + + /* + * Only proceed if the fence object didn't change in the meanwhile. + * Otherwise assume the work has been already carried out by another + * thread that re-aquired the lock before us. + */ + proceed = fence == fenced_buf->fence ? TRUE : FALSE; + + ops->fence_reference(ops, &fence, NULL); + + if(proceed && finished == 0) { + /* + * Remove from the fenced list + */ + + boolean destroyed; + + destroyed = fenced_buffer_remove_locked(fenced_mgr, fenced_buf); + + /* TODO: remove consequents buffers with the same fence? */ + + assert(!destroyed); + + fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE; + + ret = PIPE_OK; } - /* Remove from the fenced list */ - /* TODO: remove consequents */ - _fenced_buffer_remove(fenced_list, fenced_buf); } - fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE; - return PIPE_OK; + return ret; } /** - * Free as many fenced buffers from the list head as possible. + * Remove as many fenced buffers from the fenced list as possible. + * + * Returns TRUE if at least one buffer was removed. */ -static void -_fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, - int wait) +static boolean +fenced_manager_check_signalled_locked(struct fenced_manager *fenced_mgr, + boolean wait) { - struct pb_fence_ops *ops = fenced_list->ops; + struct pb_fence_ops *ops = fenced_mgr->ops; struct list_head *curr, *next; struct fenced_buffer *fenced_buf; - struct pb_buffer *pb_buf; struct pipe_fence_handle *prev_fence = NULL; + boolean ret = FALSE; - curr = fenced_list->delayed.next; + curr = fenced_mgr->fenced.next; next = curr->next; - while(curr != &fenced_list->delayed) { + while(curr != &fenced_mgr->fenced) { fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); if(fenced_buf->fence != prev_fence) { int signaled; - if (wait) + + if (wait) { signaled = ops->fence_finish(ops, fenced_buf->fence, 0); - else + + /* + * Don't return just now. Instead preemptively check if the + * following buffers' fences already expired, without further waits. + */ + wait = FALSE; + } + else { signaled = ops->fence_signalled(ops, fenced_buf->fence, 0); - if (signaled != 0) - break; + } + + if (signaled != 0) { + return ret; + } + prev_fence = fenced_buf->fence; } else { + /* This buffer's fence object is identical to the previous buffer's + * fence object, so no need to check the fence again. + */ assert(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0); } - _fenced_buffer_remove(fenced_list, fenced_buf); + fenced_buffer_remove_locked(fenced_mgr, fenced_buf); + + ret = TRUE; + + curr = next; + next = curr->next; + } + + return ret; +} + + +/** + * Try to free some GPU memory by backing it up into CPU memory. + * + * Returns TRUE if at least one buffer was freed. + */ +static boolean +fenced_manager_free_gpu_storage_locked(struct fenced_manager *fenced_mgr) +{ + struct list_head *curr, *next; + struct fenced_buffer *fenced_buf; - curr = next; + curr = fenced_mgr->unfenced.next; + next = curr->next; + while(curr != &fenced_mgr->unfenced) { + fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); + + /* + * We can only move storage if the buffer is not mapped and not + * validated. + */ + if(fenced_buf->buffer && + !fenced_buf->mapcount && + !fenced_buf->vl) { + enum pipe_error ret; + + ret = fenced_buffer_create_cpu_storage_locked(fenced_mgr, fenced_buf); + if(ret == PIPE_OK) { + ret = fenced_buffer_copy_storage_to_cpu_locked(fenced_buf); + if(ret == PIPE_OK) { + fenced_buffer_destroy_gpu_storage_locked(fenced_buf); + return TRUE; + } + fenced_buffer_destroy_cpu_storage_locked(fenced_buf); + } + } + + curr = next; next = curr->next; } + + return FALSE; } +/** + * Destroy CPU storage for this buffer. + */ static void -fenced_buffer_destroy(struct pb_buffer *buf) +fenced_buffer_destroy_cpu_storage_locked(struct fenced_buffer *fenced_buf) { - struct fenced_buffer *fenced_buf = fenced_buffer(buf); - struct fenced_buffer_list *fenced_list = fenced_buf->list; + if(fenced_buf->data) { + align_free(fenced_buf->data); + fenced_buf->data = NULL; + assert(fenced_buf->mgr->cpu_total_size >= fenced_buf->size); + fenced_buf->mgr->cpu_total_size -= fenced_buf->size; + } +} - pipe_mutex_lock(fenced_list->mutex); - assert(!pipe_is_referenced(&fenced_buf->base.base.reference)); - if (fenced_buf->fence) { - struct pb_fence_ops *ops = fenced_list->ops; - if(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0) { - struct list_head *curr, *prev; - curr = &fenced_buf->head; - prev = curr->prev; - do { - fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); - assert(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0); - _fenced_buffer_remove(fenced_list, fenced_buf); - curr = prev; - prev = curr->prev; - } while (curr != &fenced_list->delayed); - } - else { - /* delay destruction */ + +/** + * Create CPU storage for this buffer. + */ +static enum pipe_error +fenced_buffer_create_cpu_storage_locked(struct fenced_manager *fenced_mgr, + struct fenced_buffer *fenced_buf) +{ + assert(!fenced_buf->data); + if(fenced_buf->data) + return PIPE_OK; + + if (fenced_mgr->cpu_total_size + fenced_buf->size > fenced_mgr->max_cpu_total_size) + return PIPE_ERROR_OUT_OF_MEMORY; + + fenced_buf->data = align_malloc(fenced_buf->size, fenced_buf->desc.alignment); + if(!fenced_buf->data) + return PIPE_ERROR_OUT_OF_MEMORY; + + fenced_mgr->cpu_total_size += fenced_buf->size; + + return PIPE_OK; +} + + +/** + * Destroy the GPU storage. + */ +static void +fenced_buffer_destroy_gpu_storage_locked(struct fenced_buffer *fenced_buf) +{ + if(fenced_buf->buffer) { + pb_reference(&fenced_buf->buffer, NULL); + } +} + + +/** + * Try to create GPU storage for this buffer. + * + * This function is a shorthand around pb_manager::create_buffer for + * fenced_buffer_create_gpu_storage_locked()'s benefit. + */ +static INLINE boolean +fenced_buffer_try_create_gpu_storage_locked(struct fenced_manager *fenced_mgr, + struct fenced_buffer *fenced_buf) +{ + struct pb_manager *provider = fenced_mgr->provider; + + assert(!fenced_buf->buffer); + + fenced_buf->buffer = provider->create_buffer(fenced_mgr->provider, + fenced_buf->size, + &fenced_buf->desc); + return fenced_buf->buffer ? TRUE : FALSE; +} + + +/** + * Create GPU storage for this buffer. + */ +static enum pipe_error +fenced_buffer_create_gpu_storage_locked(struct fenced_manager *fenced_mgr, + struct fenced_buffer *fenced_buf, + boolean wait) +{ + assert(!fenced_buf->buffer); + + /* + * Check for signaled buffers before trying to allocate. + */ + fenced_manager_check_signalled_locked(fenced_mgr, FALSE); + + fenced_buffer_try_create_gpu_storage_locked(fenced_mgr, fenced_buf); + + /* + * Keep trying while there is some sort of progress: + * - fences are expiring, + * - or buffers are being being swapped out from GPU memory into CPU memory. + */ + while(!fenced_buf->buffer && + (fenced_manager_check_signalled_locked(fenced_mgr, FALSE) || + fenced_manager_free_gpu_storage_locked(fenced_mgr))) { + fenced_buffer_try_create_gpu_storage_locked(fenced_mgr, fenced_buf); + } + + if(!fenced_buf->buffer && wait) { + /* + * Same as before, but this time around, wait to free buffers if + * necessary. + */ + while(!fenced_buf->buffer && + (fenced_manager_check_signalled_locked(fenced_mgr, TRUE) || + fenced_manager_free_gpu_storage_locked(fenced_mgr))) { + fenced_buffer_try_create_gpu_storage_locked(fenced_mgr, fenced_buf); } } - else { - _fenced_buffer_destroy(fenced_buf); + + if(!fenced_buf->buffer) { + if(0) + fenced_manager_dump_locked(fenced_mgr); + + /* give up */ + return PIPE_ERROR_OUT_OF_MEMORY; } - pipe_mutex_unlock(fenced_list->mutex); + + return PIPE_OK; +} + + +static enum pipe_error +fenced_buffer_copy_storage_to_gpu_locked(struct fenced_buffer *fenced_buf) +{ + uint8_t *map; + + assert(fenced_buf->data); + assert(fenced_buf->buffer); + + map = pb_map(fenced_buf->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); + if(!map) + return PIPE_ERROR; + + memcpy(map, fenced_buf->data, fenced_buf->size); + + pb_unmap(fenced_buf->buffer); + + return PIPE_OK; +} + + +static enum pipe_error +fenced_buffer_copy_storage_to_cpu_locked(struct fenced_buffer *fenced_buf) +{ + const uint8_t *map; + + assert(fenced_buf->data); + assert(fenced_buf->buffer); + + map = pb_map(fenced_buf->buffer, PIPE_BUFFER_USAGE_CPU_READ); + if(!map) + return PIPE_ERROR; + + memcpy(fenced_buf->data, map, fenced_buf->size); + + pb_unmap(fenced_buf->buffer); + + return PIPE_OK; +} + + +static void +fenced_buffer_destroy(struct pb_buffer *buf) +{ + struct fenced_buffer *fenced_buf = fenced_buffer(buf); + struct fenced_manager *fenced_mgr = fenced_buf->mgr; + + assert(!pipe_is_referenced(&fenced_buf->base.base.reference)); + + pipe_mutex_lock(fenced_mgr->mutex); + + fenced_buffer_destroy_locked(fenced_mgr, fenced_buf); + + pipe_mutex_unlock(fenced_mgr->mutex); } static void * -fenced_buffer_map(struct pb_buffer *buf, +fenced_buffer_map(struct pb_buffer *buf, unsigned flags) { struct fenced_buffer *fenced_buf = fenced_buffer(buf); - struct fenced_buffer_list *fenced_list = fenced_buf->list; - struct pb_fence_ops *ops = fenced_list->ops; - void *map; + struct fenced_manager *fenced_mgr = fenced_buf->mgr; + struct pb_fence_ops *ops = fenced_mgr->ops; + void *map = NULL; + + pipe_mutex_lock(fenced_mgr->mutex); assert(!(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE)); - - /* Serialize writes */ - if((fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_WRITE) || - ((fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ) && (flags & PIPE_BUFFER_USAGE_CPU_WRITE))) { - if(flags & PIPE_BUFFER_USAGE_DONTBLOCK) { - /* Don't wait for the GPU to finish writing */ - if(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0) - _fenced_buffer_remove(fenced_list, fenced_buf); - else - return NULL; + + /* + * Serialize writes. + */ + while((fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_WRITE) || + ((fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ) && + (flags & PIPE_BUFFER_USAGE_CPU_WRITE))) { + + /* + * Don't wait for the GPU to finish accessing it, if blocking is forbidden. + */ + if((flags & PIPE_BUFFER_USAGE_DONTBLOCK) && + ops->fence_signalled(ops, fenced_buf->fence, 0) == 0) { + goto done; } - else { - /* Wait for the GPU to finish writing */ - _fenced_buffer_finish(fenced_buf); + + if (flags & PIPE_BUFFER_USAGE_UNSYNCHRONIZED) { + break; } + + /* + * Wait for the GPU to finish accessing. This will release and re-acquire + * the mutex, so all copies of mutable state must be discarded. + */ + fenced_buffer_finish_locked(fenced_mgr, fenced_buf); } -#if 0 - /* Check for CPU write access (read is OK) */ - if(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) { - /* this is legal -- just for debugging */ - debug_warning("concurrent CPU writes"); + if(fenced_buf->buffer) { + map = pb_map(fenced_buf->buffer, flags); } -#endif - - map = pb_map(fenced_buf->buffer, flags); + else { + assert(fenced_buf->data); + map = fenced_buf->data; + } + if(map) { ++fenced_buf->mapcount; fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE; } +done: + pipe_mutex_unlock(fenced_mgr->mutex); + return map; } @@ -333,13 +735,20 @@ static void fenced_buffer_unmap(struct pb_buffer *buf) { struct fenced_buffer *fenced_buf = fenced_buffer(buf); + struct fenced_manager *fenced_mgr = fenced_buf->mgr; + + pipe_mutex_lock(fenced_mgr->mutex); + assert(fenced_buf->mapcount); if(fenced_buf->mapcount) { - pb_unmap(fenced_buf->buffer); + if (fenced_buf->buffer) + pb_unmap(fenced_buf->buffer); --fenced_buf->mapcount; if(!fenced_buf->mapcount) fenced_buf->flags &= ~PIPE_BUFFER_USAGE_CPU_READ_WRITE; } + + pipe_mutex_unlock(fenced_mgr->mutex); } @@ -349,48 +758,72 @@ fenced_buffer_validate(struct pb_buffer *buf, unsigned flags) { struct fenced_buffer *fenced_buf = fenced_buffer(buf); + struct fenced_manager *fenced_mgr = fenced_buf->mgr; enum pipe_error ret; - + + pipe_mutex_lock(fenced_mgr->mutex); + if(!vl) { /* invalidate */ fenced_buf->vl = NULL; fenced_buf->validation_flags = 0; - return PIPE_OK; + ret = PIPE_OK; + goto done; } - + assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); assert(!(flags & ~PIPE_BUFFER_USAGE_GPU_READ_WRITE)); flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE; - /* Buffer cannot be validated in two different lists */ - if(fenced_buf->vl && fenced_buf->vl != vl) - return PIPE_ERROR_RETRY; - -#if 0 - /* Do not validate if buffer is still mapped */ - if(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) { - /* TODO: wait for the thread that mapped the buffer to unmap it */ - return PIPE_ERROR_RETRY; + /* Buffer cannot be validated in two different lists */ + if(fenced_buf->vl && fenced_buf->vl != vl) { + ret = PIPE_ERROR_RETRY; + goto done; } - /* Final sanity checking */ - assert(!(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE)); - assert(!fenced_buf->mapcount); -#endif if(fenced_buf->vl == vl && (fenced_buf->validation_flags & flags) == flags) { /* Nothing to do -- buffer already validated */ - return PIPE_OK; + ret = PIPE_OK; + goto done; + } + + /* + * Create and update GPU storage. + */ + if(!fenced_buf->buffer) { + assert(!fenced_buf->mapcount); + + ret = fenced_buffer_create_gpu_storage_locked(fenced_mgr, fenced_buf, TRUE); + if(ret != PIPE_OK) { + goto done; + } + + ret = fenced_buffer_copy_storage_to_gpu_locked(fenced_buf); + if(ret != PIPE_OK) { + fenced_buffer_destroy_gpu_storage_locked(fenced_buf); + goto done; + } + + if(fenced_buf->mapcount) { + debug_printf("warning: validating a buffer while it is still mapped\n"); + } + else { + fenced_buffer_destroy_cpu_storage_locked(fenced_buf); + } } - + ret = pb_validate(fenced_buf->buffer, vl, flags); if (ret != PIPE_OK) - return ret; - + goto done; + fenced_buf->vl = vl; fenced_buf->validation_flags |= flags; - - return PIPE_OK; + +done: + pipe_mutex_unlock(fenced_mgr->mutex); + + return ret; } @@ -398,36 +831,37 @@ static void fenced_buffer_fence(struct pb_buffer *buf, struct pipe_fence_handle *fence) { - struct fenced_buffer *fenced_buf; - struct fenced_buffer_list *fenced_list; - struct pb_fence_ops *ops; + struct fenced_buffer *fenced_buf = fenced_buffer(buf); + struct fenced_manager *fenced_mgr = fenced_buf->mgr; + struct pb_fence_ops *ops = fenced_mgr->ops; - fenced_buf = fenced_buffer(buf); - fenced_list = fenced_buf->list; - ops = fenced_list->ops; - - if(fence == fenced_buf->fence) { - /* Nothing to do */ - return; - } + pipe_mutex_lock(fenced_mgr->mutex); - assert(fenced_buf->vl); - assert(fenced_buf->validation_flags); - - pipe_mutex_lock(fenced_list->mutex); - if (fenced_buf->fence) - _fenced_buffer_remove(fenced_list, fenced_buf); - if (fence) { - ops->fence_reference(ops, &fenced_buf->fence, fence); - fenced_buf->flags |= fenced_buf->validation_flags; - _fenced_buffer_add(fenced_buf); + assert(pipe_is_referenced(&fenced_buf->base.base.reference)); + assert(fenced_buf->buffer); + + if(fence != fenced_buf->fence) { + assert(fenced_buf->vl); + assert(fenced_buf->validation_flags); + + if (fenced_buf->fence) { + boolean destroyed; + destroyed = fenced_buffer_remove_locked(fenced_mgr, fenced_buf); + assert(!destroyed); + } + if (fence) { + ops->fence_reference(ops, &fenced_buf->fence, fence); + fenced_buf->flags |= fenced_buf->validation_flags; + fenced_buffer_add_locked(fenced_mgr, fenced_buf); + } + + pb_fence(fenced_buf->buffer, fence); + + fenced_buf->vl = NULL; + fenced_buf->validation_flags = 0; } - pipe_mutex_unlock(fenced_list->mutex); - - pb_fence(fenced_buf->buffer, fence); - fenced_buf->vl = NULL; - fenced_buf->validation_flags = 0; + pipe_mutex_unlock(fenced_mgr->mutex); } @@ -437,11 +871,29 @@ fenced_buffer_get_base_buffer(struct pb_buffer *buf, pb_size *offset) { struct fenced_buffer *fenced_buf = fenced_buffer(buf); - pb_get_base_buffer(fenced_buf->buffer, base_buf, offset); + struct fenced_manager *fenced_mgr = fenced_buf->mgr; + + pipe_mutex_lock(fenced_mgr->mutex); + + /* + * This should only be called when the buffer is validated. Typically + * when processing relocations. + */ + assert(fenced_buf->vl); + assert(fenced_buf->buffer); + + if(fenced_buf->buffer) + pb_get_base_buffer(fenced_buf->buffer, base_buf, offset); + else { + *base_buf = buf; + *offset = 0; + } + + pipe_mutex_unlock(fenced_mgr->mutex); } -static const struct pb_vtbl +static const struct pb_vtbl fenced_buffer_vtbl = { fenced_buffer_destroy, fenced_buffer_map, @@ -452,147 +904,166 @@ fenced_buffer_vtbl = { }; -struct pb_buffer * -fenced_buffer_create(struct fenced_buffer_list *fenced_list, - struct pb_buffer *buffer) +/** + * Wrap a buffer in a fenced buffer. + */ +static struct pb_buffer * +fenced_bufmgr_create_buffer(struct pb_manager *mgr, + pb_size size, + const struct pb_desc *desc) { - struct fenced_buffer *buf; - - if(!buffer) - return NULL; - - buf = CALLOC_STRUCT(fenced_buffer); - if(!buf) { - pb_reference(&buffer, NULL); - return NULL; + struct fenced_manager *fenced_mgr = fenced_manager(mgr); + struct fenced_buffer *fenced_buf; + enum pipe_error ret; + + /* + * Don't stall the GPU, waste time evicting buffers, or waste memory + * trying to create a buffer that will most likely never fit into the + * graphics aperture. + */ + if(size > fenced_mgr->max_buffer_size) { + goto no_buffer; } - - pipe_reference_init(&buf->base.base.reference, 1); - buf->base.base.alignment = buffer->base.alignment; - buf->base.base.usage = buffer->base.usage; - buf->base.base.size = buffer->base.size; - - buf->base.vtbl = &fenced_buffer_vtbl; - buf->buffer = buffer; - buf->list = fenced_list; - -#ifdef DEBUG - pipe_mutex_lock(fenced_list->mutex); - LIST_ADDTAIL(&buf->head, &fenced_list->unfenced); - ++fenced_list->numUnfenced; - pipe_mutex_unlock(fenced_list->mutex); -#endif - return &buf->base; -} + fenced_buf = CALLOC_STRUCT(fenced_buffer); + if(!fenced_buf) + goto no_buffer; + pipe_reference_init(&fenced_buf->base.base.reference, 1); + fenced_buf->base.base.alignment = desc->alignment; + fenced_buf->base.base.usage = desc->usage; + fenced_buf->base.base.size = size; + fenced_buf->size = size; + fenced_buf->desc = *desc; -struct fenced_buffer_list * -fenced_buffer_list_create(struct pb_fence_ops *ops) -{ - struct fenced_buffer_list *fenced_list; + fenced_buf->base.vtbl = &fenced_buffer_vtbl; + fenced_buf->mgr = fenced_mgr; - fenced_list = CALLOC_STRUCT(fenced_buffer_list); - if (!fenced_list) - return NULL; + pipe_mutex_lock(fenced_mgr->mutex); + + /* + * Try to create GPU storage without stalling, + */ + ret = fenced_buffer_create_gpu_storage_locked(fenced_mgr, fenced_buf, FALSE); - fenced_list->ops = ops; + /* + * Attempt to use CPU memory to avoid stalling the GPU. + */ + if(ret != PIPE_OK) { + ret = fenced_buffer_create_cpu_storage_locked(fenced_mgr, fenced_buf); + } - LIST_INITHEAD(&fenced_list->delayed); - fenced_list->numDelayed = 0; - -#ifdef DEBUG - LIST_INITHEAD(&fenced_list->unfenced); - fenced_list->numUnfenced = 0; -#endif + /* + * Create GPU storage, waiting for some to be available. + */ + if(ret != PIPE_OK) { + ret = fenced_buffer_create_gpu_storage_locked(fenced_mgr, fenced_buf, TRUE); + } + + /* + * Give up. + */ + if(ret != PIPE_OK) { + goto no_storage; + } - pipe_mutex_init(fenced_list->mutex); + assert(fenced_buf->buffer || fenced_buf->data); - return fenced_list; -} + LIST_ADDTAIL(&fenced_buf->head, &fenced_mgr->unfenced); + ++fenced_mgr->num_unfenced; + pipe_mutex_unlock(fenced_mgr->mutex); + return &fenced_buf->base; -void -fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, - int wait) -{ - pipe_mutex_lock(fenced_list->mutex); - _fenced_buffer_list_check_free(fenced_list, wait); - pipe_mutex_unlock(fenced_list->mutex); +no_storage: + pipe_mutex_unlock(fenced_mgr->mutex); + FREE(fenced_buf); +no_buffer: + return NULL; } -#ifdef DEBUG -void -fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list) +static void +fenced_bufmgr_flush(struct pb_manager *mgr) { - struct pb_fence_ops *ops = fenced_list->ops; - struct list_head *curr, *next; - struct fenced_buffer *fenced_buf; + struct fenced_manager *fenced_mgr = fenced_manager(mgr); - pipe_mutex_lock(fenced_list->mutex); + pipe_mutex_lock(fenced_mgr->mutex); + while(fenced_manager_check_signalled_locked(fenced_mgr, TRUE)) + ; + pipe_mutex_unlock(fenced_mgr->mutex); - debug_printf("%10s %7s %7s %10s %s\n", - "buffer", "size", "refcount", "fence", "signalled"); - - curr = fenced_list->unfenced.next; - next = curr->next; - while(curr != &fenced_list->unfenced) { - fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); - assert(!fenced_buf->fence); - debug_printf("%10p %7u %7u\n", - (void *) fenced_buf, - fenced_buf->base.base.size, - p_atomic_read(&fenced_buf->base.base.reference.count)); - curr = next; - next = curr->next; - } - - curr = fenced_list->delayed.next; - next = curr->next; - while(curr != &fenced_list->delayed) { - int signaled; - fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); - signaled = ops->fence_signalled(ops, fenced_buf->fence, 0); - debug_printf("%10p %7u %7u %10p %s\n", - (void *) fenced_buf, - fenced_buf->base.base.size, - p_atomic_read(&fenced_buf->base.base.reference.count), - (void *) fenced_buf->fence, - signaled == 0 ? "y" : "n"); - curr = next; - next = curr->next; - } - - pipe_mutex_unlock(fenced_list->mutex); + assert(fenced_mgr->provider->flush); + if(fenced_mgr->provider->flush) + fenced_mgr->provider->flush(fenced_mgr->provider); } -#endif -void -fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list) +static void +fenced_bufmgr_destroy(struct pb_manager *mgr) { - pipe_mutex_lock(fenced_list->mutex); + struct fenced_manager *fenced_mgr = fenced_manager(mgr); + + pipe_mutex_lock(fenced_mgr->mutex); /* Wait on outstanding fences */ - while (fenced_list->numDelayed) { - pipe_mutex_unlock(fenced_list->mutex); + while (fenced_mgr->num_fenced) { + pipe_mutex_unlock(fenced_mgr->mutex); #if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) sched_yield(); #endif - _fenced_buffer_list_check_free(fenced_list, 1); - pipe_mutex_lock(fenced_list->mutex); + pipe_mutex_lock(fenced_mgr->mutex); + while(fenced_manager_check_signalled_locked(fenced_mgr, TRUE)) + ; } #ifdef DEBUG - /*assert(!fenced_list->numUnfenced);*/ + /*assert(!fenced_mgr->num_unfenced);*/ #endif - - pipe_mutex_unlock(fenced_list->mutex); - - fenced_list->ops->destroy(fenced_list->ops); - - FREE(fenced_list); + + pipe_mutex_unlock(fenced_mgr->mutex); + pipe_mutex_destroy(fenced_mgr->mutex); + + if(fenced_mgr->provider) + fenced_mgr->provider->destroy(fenced_mgr->provider); + + fenced_mgr->ops->destroy(fenced_mgr->ops); + + FREE(fenced_mgr); } +struct pb_manager * +fenced_bufmgr_create(struct pb_manager *provider, + struct pb_fence_ops *ops, + pb_size max_buffer_size, + pb_size max_cpu_total_size) +{ + struct fenced_manager *fenced_mgr; + + if(!provider) + return NULL; + + fenced_mgr = CALLOC_STRUCT(fenced_manager); + if (!fenced_mgr) + return NULL; + + fenced_mgr->base.destroy = fenced_bufmgr_destroy; + fenced_mgr->base.create_buffer = fenced_bufmgr_create_buffer; + fenced_mgr->base.flush = fenced_bufmgr_flush; + + fenced_mgr->provider = provider; + fenced_mgr->ops = ops; + fenced_mgr->max_buffer_size = max_buffer_size; + fenced_mgr->max_cpu_total_size = max_cpu_total_size; + + LIST_INITHEAD(&fenced_mgr->fenced); + fenced_mgr->num_fenced = 0; + + LIST_INITHEAD(&fenced_mgr->unfenced); + fenced_mgr->num_unfenced = 0; + + pipe_mutex_init(fenced_mgr->mutex); + + return &fenced_mgr->base; +} diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h index 034ca1e024..0372f81d0a 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h @@ -98,43 +98,6 @@ struct pb_fence_ops }; -/** - * Create a fenced buffer list. - * - * See also fenced_bufmgr_create for a more convenient way to use this. - */ -struct fenced_buffer_list * -fenced_buffer_list_create(struct pb_fence_ops *ops); - - -/** - * Walk the fenced buffer list to check and free signalled buffers. - */ -void -fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, - int wait); - - -#ifdef DEBUG -void -fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list); -#endif - - -void -fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list); - - -/** - * Wrap a buffer in a fenced buffer. - * - * NOTE: this will not increase the buffer reference count. - */ -struct pb_buffer * -fenced_buffer_create(struct fenced_buffer_list *fenced, - struct pb_buffer *buffer); - - #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h index 8c8d713078..06669917ff 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h @@ -175,7 +175,9 @@ struct pb_fence_ops; */ struct pb_manager * fenced_bufmgr_create(struct pb_manager *provider, - struct pb_fence_ops *ops); + struct pb_fence_ops *ops, + pb_size max_buffer_size, + pb_size max_cpu_total_size); struct pb_manager * diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c index 6e3214ca9c..8f74180a11 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c @@ -371,6 +371,9 @@ pb_debug_manager_create_buffer(struct pb_manager *_mgr, struct pb_desc real_desc; pb_size real_size; + assert(size); + assert(desc->alignment); + buf = CALLOC_STRUCT(pb_debug_buffer); if(!buf) return NULL; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c deleted file mode 100644 index 97dd1427fd..0000000000 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c +++ /dev/null @@ -1,152 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ - -/** - * \file - * A buffer manager that wraps buffers in fenced buffers. - * - * \author Jose Fonseca <jrfonseca@tungstengraphics.dot.com> - */ - - -#include "util/u_debug.h" -#include "util/u_memory.h" - -#include "pb_buffer.h" -#include "pb_buffer_fenced.h" -#include "pb_bufmgr.h" - - -struct fenced_pb_manager -{ - struct pb_manager base; - - struct pb_manager *provider; - - struct fenced_buffer_list *fenced_list; -}; - - -static INLINE struct fenced_pb_manager * -fenced_pb_manager(struct pb_manager *mgr) -{ - assert(mgr); - return (struct fenced_pb_manager *)mgr; -} - - -static struct pb_buffer * -fenced_bufmgr_create_buffer(struct pb_manager *mgr, - pb_size size, - const struct pb_desc *desc) -{ - struct fenced_pb_manager *fenced_mgr = fenced_pb_manager(mgr); - struct pb_buffer *buf; - struct pb_buffer *fenced_buf; - - /* check for free buffers before allocating new ones */ - fenced_buffer_list_check_free(fenced_mgr->fenced_list, 0); - - buf = fenced_mgr->provider->create_buffer(fenced_mgr->provider, size, desc); - if(!buf) { - /* try harder to get a buffer */ - fenced_buffer_list_check_free(fenced_mgr->fenced_list, 1); - - buf = fenced_mgr->provider->create_buffer(fenced_mgr->provider, size, desc); - if(!buf) { -#if 0 - fenced_buffer_list_dump(fenced_mgr->fenced_list); -#endif - - /* give up */ - return NULL; - } - } - - fenced_buf = fenced_buffer_create(fenced_mgr->fenced_list, buf); - if(!fenced_buf) { - pb_reference(&buf, NULL); - } - - return fenced_buf; -} - - -static void -fenced_bufmgr_flush(struct pb_manager *mgr) -{ - struct fenced_pb_manager *fenced_mgr = fenced_pb_manager(mgr); - - fenced_buffer_list_check_free(fenced_mgr->fenced_list, TRUE); - - assert(fenced_mgr->provider->flush); - if(fenced_mgr->provider->flush) - fenced_mgr->provider->flush(fenced_mgr->provider); -} - - -static void -fenced_bufmgr_destroy(struct pb_manager *mgr) -{ - struct fenced_pb_manager *fenced_mgr = fenced_pb_manager(mgr); - - fenced_buffer_list_destroy(fenced_mgr->fenced_list); - - if(fenced_mgr->provider) - fenced_mgr->provider->destroy(fenced_mgr->provider); - - FREE(fenced_mgr); -} - - -struct pb_manager * -fenced_bufmgr_create(struct pb_manager *provider, - struct pb_fence_ops *ops) -{ - struct fenced_pb_manager *fenced_mgr; - - if(!provider) - return NULL; - - fenced_mgr = CALLOC_STRUCT(fenced_pb_manager); - if (!fenced_mgr) - return NULL; - - fenced_mgr->base.destroy = fenced_bufmgr_destroy; - fenced_mgr->base.create_buffer = fenced_bufmgr_create_buffer; - fenced_mgr->base.flush = fenced_bufmgr_flush; - - fenced_mgr->provider = provider; - fenced_mgr->fenced_list = fenced_buffer_list_create(ops); - if(!fenced_mgr->fenced_list) { - FREE(fenced_mgr); - return NULL; - } - - return &fenced_mgr->base; -} diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.c b/src/gallium/auxiliary/pipebuffer/pb_validate.c index ce40c0cf0e..903afc749d 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_validate.c +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.c @@ -39,7 +39,6 @@ #include "util/u_debug.h" #include "pb_buffer.h" -#include "pb_buffer_fenced.h" #include "pb_validate.h" diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c index de9cbc8630..e38b0be7ab 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.c +++ b/src/gallium/auxiliary/tgsi/tgsi_build.c @@ -103,6 +103,7 @@ tgsi_default_declaration( void ) declaration.File = TGSI_FILE_NULL; declaration.UsageMask = TGSI_WRITEMASK_XYZW; declaration.Interpolate = TGSI_INTERPOLATE_CONSTANT; + declaration.Dimension = 0; declaration.Semantic = 0; declaration.Centroid = 0; declaration.Invariant = 0; @@ -116,6 +117,7 @@ tgsi_build_declaration( unsigned file, unsigned usage_mask, unsigned interpolate, + unsigned dimension, unsigned semantic, unsigned centroid, unsigned invariant, @@ -130,6 +132,7 @@ tgsi_build_declaration( declaration.File = file; declaration.UsageMask = usage_mask; declaration.Interpolate = interpolate; + declaration.Dimension = dimension; declaration.Semantic = semantic; declaration.Centroid = centroid; declaration.Invariant = invariant; @@ -183,6 +186,7 @@ tgsi_build_full_declaration( full_decl->Declaration.File, full_decl->Declaration.UsageMask, full_decl->Declaration.Interpolate, + full_decl->Declaration.Dimension, full_decl->Declaration.Semantic, full_decl->Declaration.Centroid, full_decl->Declaration.Invariant, @@ -199,6 +203,20 @@ tgsi_build_full_declaration( declaration, header ); + if (full_decl->Declaration.Dimension) { + struct tgsi_declaration_dimension *dd; + + if (maxsize <= size) { + return 0; + } + dd = (struct tgsi_declaration_dimension *)&tokens[size]; + size++; + + *dd = tgsi_build_declaration_dimension(full_decl->Dim.Index2D, + declaration, + header); + } + if( full_decl->Declaration.Semantic ) { struct tgsi_declaration_semantic *ds; @@ -249,6 +267,34 @@ tgsi_build_declaration_range( return declaration_range; } +struct tgsi_declaration_dimension +tgsi_default_declaration_dimension(void) +{ + struct tgsi_declaration_dimension dd; + + dd.Index2D = 0; + dd.Padding = 0; + + return dd; +} + +struct tgsi_declaration_dimension +tgsi_build_declaration_dimension(unsigned index_2d, + struct tgsi_declaration *declaration, + struct tgsi_header *header) +{ + struct tgsi_declaration_dimension dd; + + assert(index_2d <= 0xFFFF); + + dd = tgsi_default_declaration_dimension(); + dd.Index2D = index_2d; + + declaration_grow(declaration, header); + + return dd; +} + struct tgsi_declaration_semantic tgsi_default_declaration_semantic( void ) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.h b/src/gallium/auxiliary/tgsi/tgsi_build.h index 9de2757fe4..ebee4ce5f6 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.h +++ b/src/gallium/auxiliary/tgsi/tgsi_build.h @@ -64,6 +64,7 @@ tgsi_build_declaration( unsigned file, unsigned usage_mask, unsigned interpolate, + unsigned dimension, unsigned semantic, unsigned centroid, unsigned invariant, @@ -89,6 +90,14 @@ tgsi_build_declaration_range( struct tgsi_declaration *declaration, struct tgsi_header *header ); +struct tgsi_declaration_dimension +tgsi_default_declaration_dimension(void); + +struct tgsi_declaration_dimension +tgsi_build_declaration_dimension(unsigned index_2d, + struct tgsi_declaration *declaration, + struct tgsi_header *header); + struct tgsi_declaration_semantic tgsi_default_declaration_semantic( void ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c index d7ff262f30..dd36555875 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -159,7 +159,9 @@ static const char *property_names[] = { "GS_INPUT_PRIMITIVE", "GS_OUTPUT_PRIMITIVE", - "GS_MAX_OUTPUT_VERTICES" + "GS_MAX_OUTPUT_VERTICES", + "FS_COORD_ORIGIN", + "FS_COORD_PIXEL_CENTER" }; static const char *primitive_names[] = @@ -176,29 +178,18 @@ static const char *primitive_names[] = "POLYGON" }; - -static void -_dump_register_decl( - struct dump_ctx *ctx, - uint file, - int first, - int last ) +static const char *fs_coord_origin_names[] = { - ENM( file, file_names ); + "UPPER_LEFT", + "LOWER_LEFT" +}; - /* all geometry shader inputs are two dimensional */ - if (file == TGSI_FILE_INPUT && - ctx->iter.processor.Processor == TGSI_PROCESSOR_GEOMETRY) - TXT("[]"); +static const char *fs_coord_pixel_center_names[] = +{ + "HALF_INTEGER", + "INTEGER" +}; - CHR( '[' ); - SID( first ); - if (first != last) { - TXT( ".." ); - SID( last ); - } - CHR( ']' ); -} static void _dump_register_dst( @@ -219,8 +210,13 @@ _dump_register_src( struct dump_ctx *ctx, const struct tgsi_full_src_register *src ) { + ENM(src->Register.File, file_names); + if (src->Register.Dimension) { + CHR('['); + SID(src->Dimension.Index); + CHR(']'); + } if (src->Register.Indirect) { - ENM( src->Register.File, file_names ); CHR( '[' ); ENM( src->Indirect.File, file_names ); CHR( '[' ); @@ -234,16 +230,10 @@ _dump_register_src( } CHR( ']' ); } else { - ENM( src->Register.File, file_names ); CHR( '[' ); SID( src->Register.Index ); CHR( ']' ); } - if (src->Register.Dimension) { - CHR( '[' ); - SID( src->Dimension.Index ); - CHR( ']' ); - } } static void @@ -300,11 +290,28 @@ iter_declaration( TXT( "DCL " ); - _dump_register_decl( - ctx, - decl->Declaration.File, - decl->Range.First, - decl->Range.Last ); + ENM(decl->Declaration.File, file_names); + + /* all geometry shader inputs are two dimensional */ + if (decl->Declaration.File == TGSI_FILE_INPUT && + iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) { + TXT("[]"); + } + + if (decl->Declaration.Dimension) { + CHR('['); + SID(decl->Dim.Index2D); + CHR(']'); + } + + CHR('['); + SID(decl->Range.First); + if (decl->Range.First != decl->Range.Last) { + TXT(".."); + SID(decl->Range.Last); + } + CHR(']'); + _dump_writemask( ctx, decl->Declaration.UsageMask ); @@ -373,6 +380,12 @@ iter_property( case TGSI_PROPERTY_GS_OUTPUT_PRIM: ENM(prop->u[i].Data, primitive_names); break; + case TGSI_PROPERTY_FS_COORD_ORIGIN: + ENM(prop->u[i].Data, fs_coord_origin_names); + break; + case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: + ENM(prop->u[i].Data, fs_coord_pixel_center_names); + break; default: SID( prop->u[i].Data ); break; diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 118a638ab4..fbb9aa0e63 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -953,107 +953,90 @@ micro_sub( } static void -fetch_src_file_channel( - const struct tgsi_exec_machine *mach, - const uint file, - const uint swizzle, - const union tgsi_exec_channel *index, - union tgsi_exec_channel *chan ) -{ - switch( swizzle ) { - case TGSI_SWIZZLE_X: - case TGSI_SWIZZLE_Y: - case TGSI_SWIZZLE_Z: - case TGSI_SWIZZLE_W: - switch( file ) { - case TGSI_FILE_CONSTANT: - assert(mach->Consts); - if (index->i[0] < 0) - chan->f[0] = 0.0f; - else - chan->f[0] = mach->Consts[index->i[0]][swizzle]; - if (index->i[1] < 0) - chan->f[1] = 0.0f; - else - chan->f[1] = mach->Consts[index->i[1]][swizzle]; - if (index->i[2] < 0) - chan->f[2] = 0.0f; - else - chan->f[2] = mach->Consts[index->i[2]][swizzle]; - if (index->i[3] < 0) - chan->f[3] = 0.0f; - else - chan->f[3] = mach->Consts[index->i[3]][swizzle]; - break; +fetch_src_file_channel(const struct tgsi_exec_machine *mach, + const uint file, + const uint swizzle, + const union tgsi_exec_channel *index, + const union tgsi_exec_channel *index2D, + union tgsi_exec_channel *chan) +{ + uint i; - case TGSI_FILE_INPUT: - case TGSI_FILE_SYSTEM_VALUE: - chan->u[0] = mach->Inputs[index->i[0]].xyzw[swizzle].u[0]; - chan->u[1] = mach->Inputs[index->i[1]].xyzw[swizzle].u[1]; - chan->u[2] = mach->Inputs[index->i[2]].xyzw[swizzle].u[2]; - chan->u[3] = mach->Inputs[index->i[3]].xyzw[swizzle].u[3]; - break; + switch (file) { + case TGSI_FILE_CONSTANT: + for (i = 0; i < QUAD_SIZE; i++) { + assert(index2D->i[i] >= 0 && index2D->i[i] < PIPE_MAX_CONSTANT_BUFFERS); + assert(mach->Consts[index2D->i[i]]); - case TGSI_FILE_TEMPORARY: - assert(index->i[0] < TGSI_EXEC_NUM_TEMPS); - chan->u[0] = mach->Temps[index->i[0]].xyzw[swizzle].u[0]; - chan->u[1] = mach->Temps[index->i[1]].xyzw[swizzle].u[1]; - chan->u[2] = mach->Temps[index->i[2]].xyzw[swizzle].u[2]; - chan->u[3] = mach->Temps[index->i[3]].xyzw[swizzle].u[3]; - break; + if (index->i[i] < 0) { + chan->u[i] = 0; + } else { + const uint *p = (const uint *)mach->Consts[index2D->i[i]]; - case TGSI_FILE_IMMEDIATE: - assert( index->i[0] < (int) mach->ImmLimit ); - chan->f[0] = mach->Imms[index->i[0]][swizzle]; - assert( index->i[1] < (int) mach->ImmLimit ); - chan->f[1] = mach->Imms[index->i[1]][swizzle]; - assert( index->i[2] < (int) mach->ImmLimit ); - chan->f[2] = mach->Imms[index->i[2]][swizzle]; - assert( index->i[3] < (int) mach->ImmLimit ); - chan->f[3] = mach->Imms[index->i[3]][swizzle]; - break; + chan->u[i] = p[index->i[i] * 4 + swizzle]; + } + } + break; - case TGSI_FILE_ADDRESS: - chan->u[0] = mach->Addrs[index->i[0]].xyzw[swizzle].u[0]; - chan->u[1] = mach->Addrs[index->i[1]].xyzw[swizzle].u[1]; - chan->u[2] = mach->Addrs[index->i[2]].xyzw[swizzle].u[2]; - chan->u[3] = mach->Addrs[index->i[3]].xyzw[swizzle].u[3]; - break; + case TGSI_FILE_INPUT: + case TGSI_FILE_SYSTEM_VALUE: + for (i = 0; i < QUAD_SIZE; i++) { + /* XXX: 2D indexing */ + chan->u[i] = mach->Inputs[index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i]].xyzw[swizzle].u[i]; + } + break; - case TGSI_FILE_PREDICATE: - assert(index->i[0] < TGSI_EXEC_NUM_PREDS); - assert(index->i[1] < TGSI_EXEC_NUM_PREDS); - assert(index->i[2] < TGSI_EXEC_NUM_PREDS); - assert(index->i[3] < TGSI_EXEC_NUM_PREDS); - chan->u[0] = mach->Predicates[0].xyzw[swizzle].u[0]; - chan->u[1] = mach->Predicates[0].xyzw[swizzle].u[1]; - chan->u[2] = mach->Predicates[0].xyzw[swizzle].u[2]; - chan->u[3] = mach->Predicates[0].xyzw[swizzle].u[3]; - break; + case TGSI_FILE_TEMPORARY: + for (i = 0; i < QUAD_SIZE; i++) { + assert(index->i[i] < TGSI_EXEC_NUM_TEMPS); + assert(index2D->i[i] == 0); - case TGSI_FILE_OUTPUT: - /* vertex/fragment output vars can be read too */ - chan->u[0] = mach->Outputs[index->i[0]].xyzw[swizzle].u[0]; - chan->u[1] = mach->Outputs[index->i[1]].xyzw[swizzle].u[1]; - chan->u[2] = mach->Outputs[index->i[2]].xyzw[swizzle].u[2]; - chan->u[3] = mach->Outputs[index->i[3]].xyzw[swizzle].u[3]; - break; + chan->u[i] = mach->Temps[index->i[i]].xyzw[swizzle].u[i]; + } + break; - default: - assert( 0 ); - chan->u[0] = 0; - chan->u[1] = 0; - chan->u[2] = 0; - chan->u[3] = 0; + case TGSI_FILE_IMMEDIATE: + for (i = 0; i < QUAD_SIZE; i++) { + assert(index->i[i] >= 0 && index->i[i] < (int)mach->ImmLimit); + assert(index2D->i[i] == 0); + + chan->f[i] = mach->Imms[index->i[i]][swizzle]; + } + break; + + case TGSI_FILE_ADDRESS: + for (i = 0; i < QUAD_SIZE; i++) { + assert(index->i[i] >= 0); + assert(index2D->i[i] == 0); + + chan->u[i] = mach->Addrs[index->i[i]].xyzw[swizzle].u[i]; + } + break; + + case TGSI_FILE_PREDICATE: + for (i = 0; i < QUAD_SIZE; i++) { + assert(index->i[i] >= 0 && index->i[i] < TGSI_EXEC_NUM_PREDS); + assert(index2D->i[i] == 0); + + chan->u[i] = mach->Predicates[0].xyzw[swizzle].u[i]; + } + break; + + case TGSI_FILE_OUTPUT: + /* vertex/fragment output vars can be read too */ + for (i = 0; i < QUAD_SIZE; i++) { + assert(index->i[i] >= 0); + assert(index2D->i[i] == 0); + + chan->u[i] = mach->Outputs[index->i[i]].xyzw[swizzle].u[i]; } break; default: - assert( 0 ); - chan->u[0] = 0; - chan->u[1] = 0; - chan->u[2] = 0; - chan->u[3] = 0; + assert(0); + for (i = 0; i < QUAD_SIZE; i++) { + chan->u[i] = 0; + } } } @@ -1065,6 +1048,7 @@ fetch_source(const struct tgsi_exec_machine *mach, enum tgsi_exec_datatype src_datatype) { union tgsi_exec_channel index; + union tgsi_exec_channel index2D; uint swizzle; /* We start with a direct index into a register file. @@ -1103,12 +1087,12 @@ fetch_source(const struct tgsi_exec_machine *mach, /* get current value of address register[swizzle] */ swizzle = tgsi_util_get_src_register_swizzle( ®->Indirect, CHAN_X ); - fetch_src_file_channel( - mach, - reg->Indirect.File, - swizzle, - &index2, - &indir_index ); + fetch_src_file_channel(mach, + reg->Indirect.File, + swizzle, + &index2, + &ZeroVec, + &indir_index); /* add value of address register to the offset */ index.i[0] += indir_index.i[0]; @@ -1129,44 +1113,22 @@ fetch_source(const struct tgsi_exec_machine *mach, * subscript to a register file. Effectively it means that * the register file is actually a 2D array of registers. * - * file[1][3] == file[1*sizeof(file[1])+3], + * file[3][1], * where: * [3] = Dimension.Index */ if (reg->Register.Dimension) { - /* The size of the first-order array depends on the register file type. - * We need to multiply the index to the first array to get an effective, - * "flat" index that points to the beginning of the second-order array. - */ - switch (reg->Register.File) { - case TGSI_FILE_INPUT: - case TGSI_FILE_SYSTEM_VALUE: - index.i[0] *= TGSI_EXEC_MAX_INPUT_ATTRIBS; - index.i[1] *= TGSI_EXEC_MAX_INPUT_ATTRIBS; - index.i[2] *= TGSI_EXEC_MAX_INPUT_ATTRIBS; - index.i[3] *= TGSI_EXEC_MAX_INPUT_ATTRIBS; - break; - case TGSI_FILE_CONSTANT: - index.i[0] *= TGSI_EXEC_MAX_CONST_BUFFER; - index.i[1] *= TGSI_EXEC_MAX_CONST_BUFFER; - index.i[2] *= TGSI_EXEC_MAX_CONST_BUFFER; - index.i[3] *= TGSI_EXEC_MAX_CONST_BUFFER; - break; - default: - assert( 0 ); - } - - index.i[0] += reg->Dimension.Index; - index.i[1] += reg->Dimension.Index; - index.i[2] += reg->Dimension.Index; - index.i[3] += reg->Dimension.Index; + index2D.i[0] = + index2D.i[1] = + index2D.i[2] = + index2D.i[3] = reg->Dimension.Index; /* Again, the second subscript index can be addressed indirectly * identically to the first one. * Nothing stops us from indirectly addressing the indirect register, * but there is no need for that, so we won't exercise it. * - * file[1][ind[4].y+3], + * file[ind[4].y+3][1], * where: * ind = DimIndirect.File * [4] = DimIndirect.Index @@ -1184,24 +1146,25 @@ fetch_source(const struct tgsi_exec_machine *mach, index2.i[3] = reg->DimIndirect.Index; swizzle = tgsi_util_get_src_register_swizzle( ®->DimIndirect, CHAN_X ); - fetch_src_file_channel( - mach, - reg->DimIndirect.File, - swizzle, - &index2, - &indir_index ); - - index.i[0] += indir_index.i[0]; - index.i[1] += indir_index.i[1]; - index.i[2] += indir_index.i[2]; - index.i[3] += indir_index.i[3]; + fetch_src_file_channel(mach, + reg->DimIndirect.File, + swizzle, + &index2, + &ZeroVec, + &indir_index); + + index2D.i[0] += indir_index.i[0]; + index2D.i[1] += indir_index.i[1]; + index2D.i[2] += indir_index.i[2]; + index2D.i[3] += indir_index.i[3]; /* for disabled execution channels, zero-out the index to * avoid using a potential garbage value. */ for (i = 0; i < QUAD_SIZE; i++) { - if ((execmask & (1 << i)) == 0) - index.i[i] = 0; + if ((execmask & (1 << i)) == 0) { + index2D.i[i] = 0; + } } } @@ -1209,15 +1172,20 @@ fetch_source(const struct tgsi_exec_machine *mach, * files, we would have to check whether Dimension is followed * by a dimension register and continue the saga. */ + } else { + index2D.i[0] = + index2D.i[1] = + index2D.i[2] = + index2D.i[3] = 0; } swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index ); - fetch_src_file_channel( - mach, - reg->Register.File, - swizzle, - &index, - chan ); + fetch_src_file_channel(mach, + reg->Register.File, + swizzle, + &index, + &index2D, + chan); if (reg->Register.Absolute) { if (src_datatype == TGSI_EXEC_DATA_FLOAT) { @@ -1280,12 +1248,12 @@ store_dest(struct tgsi_exec_machine *mach, swizzle = tgsi_util_get_src_register_swizzle( ®->Indirect, CHAN_X ); /* fetch values from the address/indirection register */ - fetch_src_file_channel( - mach, - reg->Indirect.File, - swizzle, - &index, - &indir_index ); + fetch_src_file_channel(mach, + reg->Indirect.File, + swizzle, + &index, + &ZeroVec, + &indir_index); /* save indirection offset */ offset = indir_index.i[0]; diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h index 59e3b445cc..a22873e4c2 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.h +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h @@ -260,7 +260,7 @@ struct tgsi_exec_machine struct tgsi_sampler **Samplers; unsigned ImmLimit; - const float (*Consts)[4]; + const void *Consts[PIPE_MAX_CONSTANT_BUFFERS]; const struct tgsi_token *Tokens; /**< Declarations, instructions */ unsigned Processor; /**< TGSI_PROCESSOR_x */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c index 8c7062d850..fd37fc3079 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.c +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c @@ -109,6 +109,10 @@ tgsi_parse_token( next_token( ctx, &decl->Range ); + if (decl->Declaration.Dimension) { + next_token(ctx, &decl->Dim); + } + if( decl->Declaration.Semantic ) { next_token( ctx, &decl->Semantic ); } diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h index 439a57269b..8150e3cd29 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.h +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h @@ -58,6 +58,7 @@ struct tgsi_full_declaration { struct tgsi_declaration Declaration; struct tgsi_declaration_range Range; + struct tgsi_declaration_dimension Dim; struct tgsi_declaration_semantic Semantic; }; diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c index e1e4f97967..91e1b27da1 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c @@ -335,10 +335,6 @@ iter_instruction( fill_scan_register1d(ind_reg, inst->Src[i].Indirect.File, inst->Src[i].Indirect.Index); - if (!(ind_reg->file == TGSI_FILE_ADDRESS || ind_reg->file == TGSI_FILE_LOOP) || - ind_reg->indices[0] != 0) { - report_warning(ctx, "Indirect register neither ADDR[0] nor LOOP[0]"); - } check_register_usage( ctx, ind_reg, @@ -412,12 +408,16 @@ iter_declaration( uint vert; for (vert = 0; vert < ctx->implied_array_size; ++vert) { scan_register *reg = MALLOC(sizeof(scan_register)); - fill_scan_register2d(reg, file, vert, i); + fill_scan_register2d(reg, file, i, vert); check_and_declare(ctx, reg); } } else { scan_register *reg = MALLOC(sizeof(scan_register)); - fill_scan_register1d(reg, file, i); + if (decl->Declaration.Dimension) { + fill_scan_register2d(reg, file, i, decl->Dim.Index2D); + } else { + fill_scan_register1d(reg, file, i); + } check_and_declare(ctx, reg); } } diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c index a6cc773003..b9be8dc0a3 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_scan.c +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c @@ -101,12 +101,10 @@ tgsi_scan_shader(const struct tgsi_token *tokens, src->Register.File == TGSI_FILE_SYSTEM_VALUE) { const int ind = src->Register.Index; if (info->input_semantic_name[ind] == TGSI_SEMANTIC_FOG) { - if (src->Register.SwizzleX == TGSI_SWIZZLE_X) { - info->uses_fogcoord = TRUE; - } - else if (src->Register.SwizzleX == TGSI_SWIZZLE_Y) { - info->uses_frontfacing = TRUE; - } + info->uses_fogcoord = TRUE; + } + else if (info->input_semantic_name[ind] == TGSI_SEMANTIC_FACE) { + info->uses_frontfacing = TRUE; } } } diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c index 9fcffeda36..96be353e26 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_text.c +++ b/src/gallium/auxiliary/tgsi/tgsi_text.c @@ -553,7 +553,7 @@ parse_register_dcl_bracket( report_error( ctx, "Expected literal unsigned integer" ); return FALSE; } - bracket->first = (int) uindex; + bracket->first = uindex; eat_opt_white( &ctx->cur ); @@ -617,10 +617,12 @@ parse_register_dcl( * input primitive. so we want to declare just * the index relevant to the semantics which is in * the second bracket */ - if (ctx->processor == TGSI_PROCESSOR_GEOMETRY) { + if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) { brackets[0] = brackets[1]; + *num_brackets = 1; + } else { + *num_brackets = 2; } - *num_brackets = 2; } return TRUE; @@ -738,6 +740,13 @@ parse_src_operand( return FALSE; src->Register.File = file; + if (parsed_opt_brackets) { + src->Register.Dimension = 1; + src->Dimension.Indirect = 0; + src->Dimension.Dimension = 0; + src->Dimension.Index = bracket[0].index; + bracket[0] = bracket[1]; + } src->Register.Index = bracket[0].index; if (bracket[0].ind_file != TGSI_FILE_NULL) { src->Register.Indirect = 1; @@ -748,12 +757,6 @@ parse_src_operand( src->Indirect.SwizzleZ = bracket[0].ind_comp; src->Indirect.SwizzleW = bracket[0].ind_comp; } - if (parsed_opt_brackets) { - src->Register.Dimension = 1; - src->Dimension.Indirect = 0; - src->Dimension.Dimension = 0; - src->Dimension.Index = bracket[1].index; - } /* Parse optional swizzle. */ @@ -933,7 +936,8 @@ static const char *semantic_names[TGSI_SEMANTIC_COUNT] = "NORMAL", "FACE", "EDGEFLAG", - "PRIM_ID" + "PRIM_ID", + "INSTANCEID" }; static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] = @@ -968,8 +972,17 @@ static boolean parse_declaration( struct translate_ctx *ctx ) decl = tgsi_default_full_declaration(); decl.Declaration.File = file; decl.Declaration.UsageMask = writemask; - decl.Range.First = brackets[0].first; - decl.Range.Last = brackets[0].last; + + if (num_brackets == 1) { + decl.Range.First = brackets[0].first; + decl.Range.Last = brackets[0].last; + } else { + decl.Range.First = brackets[1].first; + decl.Range.Last = brackets[1].last; + + decl.Declaration.Dimension = 1; + decl.Dim.Index2D = brackets[0].first; + } cur = ctx->cur; eat_opt_white( &cur ); @@ -1116,7 +1129,9 @@ static const char *property_names[] = { "GS_INPUT_PRIMITIVE", "GS_OUTPUT_PRIMITIVE", - "GS_MAX_OUTPUT_VERTICES" + "GS_MAX_OUTPUT_VERTICES", + "FS_COORD_ORIGIN", + "FS_COORD_PIXEL_CENTER" }; static const char *primitive_names[] = @@ -1133,6 +1148,19 @@ static const char *primitive_names[] = "POLYGON" }; +static const char *fs_coord_origin_names[] = +{ + "UPPER_LEFT", + "LOWER_LEFT" +}; + +static const char *fs_coord_pixel_center_names[] = +{ + "HALF_INTEGER", + "INTEGER" +}; + + static boolean parse_primitive( const char **pcur, uint *primitive ) { @@ -1150,6 +1178,40 @@ parse_primitive( const char **pcur, uint *primitive ) return FALSE; } +static boolean +parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin ) +{ + uint i; + + for (i = 0; i < sizeof(fs_coord_origin_names) / sizeof(fs_coord_origin_names[0]); i++) { + const char *cur = *pcur; + + if (str_match_no_case( &cur, fs_coord_origin_names[i])) { + *fs_coord_origin = i; + *pcur = cur; + return TRUE; + } + } + return FALSE; +} + +static boolean +parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center ) +{ + uint i; + + for (i = 0; i < sizeof(fs_coord_pixel_center_names) / sizeof(fs_coord_pixel_center_names[0]); i++) { + const char *cur = *pcur; + + if (str_match_no_case( &cur, fs_coord_pixel_center_names[i])) { + *fs_coord_pixel_center = i; + *pcur = cur; + return TRUE; + } + } + return FALSE; +} + static boolean parse_property( struct translate_ctx *ctx ) { @@ -1191,6 +1253,18 @@ static boolean parse_property( struct translate_ctx *ctx ) ctx->implied_array_size = u_vertices_per_prim(values[0]); } break; + case TGSI_PROPERTY_FS_COORD_ORIGIN: + if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) { + report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" ); + return FALSE; + } + break; + case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: + if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) { + report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" ); + return FALSE; + } + break; default: if (!parse_uint(&ctx->cur, &values[0] )) { report_error( ctx, "Expected unsigned integer as property!" ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c index 8bd6f68dcc..0ae46785bb 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -44,6 +44,7 @@ union tgsi_any_token { struct tgsi_property_data prop_data; struct tgsi_declaration decl; struct tgsi_declaration_range decl_range; + struct tgsi_declaration_dimension decl_dim; struct tgsi_declaration_semantic decl_semantic; struct tgsi_immediate imm; union tgsi_immediate_data imm_data; @@ -75,6 +76,14 @@ struct ureg_tokens { #define UREG_MAX_LOOP 1 #define UREG_MAX_PRED 1 +struct const_decl { + struct { + unsigned first; + unsigned last; + } constant_range[UREG_MAX_CONSTANT_RANGE]; + unsigned nr_constant_ranges; +}; + #define DOMAIN_DECL 0 #define DOMAIN_INSN 1 @@ -127,13 +136,14 @@ struct ureg_program unsigned temps_active[UREG_MAX_TEMP / 32]; unsigned nr_temps; - struct { - unsigned first; - unsigned last; - } constant_range[UREG_MAX_CONSTANT_RANGE]; - unsigned nr_constant_ranges; + struct const_decl const_decls; + struct const_decl const_decls2D[PIPE_MAX_CONSTANT_BUFFERS]; unsigned property_gs_input_prim; + unsigned property_gs_output_prim; + unsigned property_gs_max_vertices; + unsigned char property_fs_coord_origin; /* = TGSI_FS_COORD_ORIGIN_* */ + unsigned char property_fs_coord_pixel_center; /* = TGSI_FS_COORD_PIXEL_CENTER_* */ unsigned nr_addrs; unsigned nr_preds; @@ -235,36 +245,40 @@ ureg_dst_register( unsigned file, return dst; } -static INLINE struct ureg_src -ureg_src_register( unsigned file, - unsigned index ) + +void +ureg_property_gs_input_prim(struct ureg_program *ureg, + unsigned input_prim) { - struct ureg_src src; - - src.File = file; - src.SwizzleX = TGSI_SWIZZLE_X; - src.SwizzleY = TGSI_SWIZZLE_Y; - src.SwizzleZ = TGSI_SWIZZLE_Z; - src.SwizzleW = TGSI_SWIZZLE_W; - src.Indirect = 0; - src.IndirectIndex = 0; - src.IndirectSwizzle = 0; - src.Absolute = 0; - src.Index = index; - src.Negate = 0; - src.Dimension = 0; - src.DimensionIndex = 0; - - return src; + ureg->property_gs_input_prim = input_prim; } +void +ureg_property_gs_output_prim(struct ureg_program *ureg, + unsigned output_prim) +{ + ureg->property_gs_output_prim = output_prim; +} +void +ureg_property_gs_max_vertices(struct ureg_program *ureg, + unsigned max_vertices) +{ + ureg->property_gs_max_vertices = max_vertices; +} void -ureg_property_gs_input_prim(struct ureg_program *ureg, - unsigned gs_input_prim) +ureg_property_fs_coord_origin(struct ureg_program *ureg, + unsigned fs_coord_origin) +{ + ureg->property_fs_coord_origin = fs_coord_origin; +} + +void +ureg_property_fs_coord_pixel_center(struct ureg_program *ureg, + unsigned fs_coord_pixel_center) { - ureg->property_gs_input_prim = gs_input_prim; + ureg->property_fs_coord_pixel_center = fs_coord_pixel_center; } @@ -374,62 +388,92 @@ out: /* Returns a new constant register. Keep track of which have been * referred to so that we can emit decls later. * + * Constant operands declared with this function must be addressed + * with a two-dimensional index. + * * There is nothing in this code to bind this constant to any tracked * value or manage any constant_buffer contents -- that's the * resposibility of the calling code. */ -struct ureg_src ureg_DECL_constant(struct ureg_program *ureg, - unsigned index ) +void +ureg_DECL_constant2D(struct ureg_program *ureg, + unsigned first, + unsigned last, + unsigned index2D) +{ + struct const_decl *decl = &ureg->const_decls2D[index2D]; + + assert(index2D < PIPE_MAX_CONSTANT_BUFFERS); + + if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) { + uint i = decl->nr_constant_ranges++; + + decl->constant_range[i].first = first; + decl->constant_range[i].last = last; + } +} + + +/* A one-dimensional, depricated version of ureg_DECL_constant2D(). + * + * Constant operands declared with this function must be addressed + * with a one-dimensional index. + */ +struct ureg_src +ureg_DECL_constant(struct ureg_program *ureg, + unsigned index) { + struct const_decl *decl = &ureg->const_decls; unsigned minconst = index, maxconst = index; unsigned i; /* Inside existing range? */ - for (i = 0; i < ureg->nr_constant_ranges; i++) { - if (ureg->constant_range[i].first <= index && - ureg->constant_range[i].last >= index) + for (i = 0; i < decl->nr_constant_ranges; i++) { + if (decl->constant_range[i].first <= index && + decl->constant_range[i].last >= index) { goto out; + } } /* Extend existing range? */ - for (i = 0; i < ureg->nr_constant_ranges; i++) { - if (ureg->constant_range[i].last == index - 1) { - ureg->constant_range[i].last = index; + for (i = 0; i < decl->nr_constant_ranges; i++) { + if (decl->constant_range[i].last == index - 1) { + decl->constant_range[i].last = index; goto out; } - if (ureg->constant_range[i].first == index + 1) { - ureg->constant_range[i].first = index; + if (decl->constant_range[i].first == index + 1) { + decl->constant_range[i].first = index; goto out; } - minconst = MIN2(minconst, ureg->constant_range[i].first); - maxconst = MAX2(maxconst, ureg->constant_range[i].last); + minconst = MIN2(minconst, decl->constant_range[i].first); + maxconst = MAX2(maxconst, decl->constant_range[i].last); } /* Create new range? */ - if (ureg->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) { - i = ureg->nr_constant_ranges++; - ureg->constant_range[i].first = index; - ureg->constant_range[i].last = index; + if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) { + i = decl->nr_constant_ranges++; + decl->constant_range[i].first = index; + decl->constant_range[i].last = index; goto out; } /* Collapse all ranges down to one: */ i = 0; - ureg->constant_range[0].first = minconst; - ureg->constant_range[0].last = maxconst; - ureg->nr_constant_ranges = 1; + decl->constant_range[0].first = minconst; + decl->constant_range[0].last = maxconst; + decl->nr_constant_ranges = 1; out: - assert(i < ureg->nr_constant_ranges); - assert(ureg->constant_range[i].first <= index); - assert(ureg->constant_range[i].last >= index); - return ureg_src_register( TGSI_FILE_CONSTANT, index ); + assert(i < decl->nr_constant_ranges); + assert(decl->constant_range[i].first <= index); + assert(decl->constant_range[i].last >= index); + return ureg_src_register(TGSI_FILE_CONSTANT, index); } @@ -578,7 +622,7 @@ decl_immediate( struct ureg_program *ureg, unsigned type ) { unsigned i, j; - unsigned swizzle; + unsigned swizzle = 0; /* Could do a first pass where we examine all existing immediates * without expanding. @@ -656,6 +700,35 @@ ureg_DECL_immediate_uint( struct ureg_program *ureg, struct ureg_src +ureg_DECL_immediate_block_uint( struct ureg_program *ureg, + const unsigned *v, + unsigned nr ) +{ + uint index; + uint i; + + if (ureg->nr_immediates + (nr + 3) / 4 > UREG_MAX_IMMEDIATE) { + set_bad(ureg); + return ureg_src_register(TGSI_FILE_IMMEDIATE, 0); + } + + index = ureg->nr_immediates; + ureg->nr_immediates += (nr + 3) / 4; + + for (i = index; i < ureg->nr_immediates; i++) { + ureg->immediate[i].type = TGSI_IMM_UINT32; + ureg->immediate[i].nr = nr > 4 ? 4 : nr; + memcpy(ureg->immediate[i].value.u, + &v[(i - index) * 4], + ureg->immediate[i].nr * sizeof(uint)); + nr -= 4; + } + + return ureg_src_register(TGSI_FILE_IMMEDIATE, index); +} + + +struct ureg_src ureg_DECL_immediate_int( struct ureg_program *ureg, const int *v, unsigned nr ) @@ -691,7 +764,7 @@ ureg_emit_src( struct ureg_program *ureg, if (src.Indirect) { out[0].src.Indirect = 1; out[n].value = 0; - out[n].src.File = TGSI_FILE_ADDRESS; + out[n].src.File = src.IndirectFile; out[n].src.SwizzleX = src.IndirectSwizzle; out[n].src.SwizzleY = src.IndirectSwizzle; out[n].src.SwizzleZ = src.IndirectSwizzle; @@ -1058,6 +1131,31 @@ static void emit_decl_range( struct ureg_program *ureg, } static void +emit_decl_range2D(struct ureg_program *ureg, + unsigned file, + unsigned first, + unsigned last, + unsigned index2D) +{ + union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 3; + out[0].decl.File = file; + out[0].decl.UsageMask = 0xf; + out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT; + out[0].decl.Dimension = 1; + + out[1].value = 0; + out[1].decl_range.First = first; + out[1].decl_range.Last = last; + + out[2].value = 0; + out[2].decl_dim.Index2D = index2D; +} + +static void emit_immediate( struct ureg_program *ureg, const unsigned *v, unsigned type ) @@ -1104,6 +1202,38 @@ static void emit_decls( struct ureg_program *ureg ) ureg->property_gs_input_prim); } + if (ureg->property_gs_output_prim != ~0) { + assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); + + emit_property(ureg, + TGSI_PROPERTY_GS_OUTPUT_PRIM, + ureg->property_gs_output_prim); + } + + if (ureg->property_gs_max_vertices != ~0) { + assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); + + emit_property(ureg, + TGSI_PROPERTY_GS_MAX_VERTICES, + ureg->property_gs_max_vertices); + } + + if (ureg->property_fs_coord_origin) { + assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); + + emit_property(ureg, + TGSI_PROPERTY_FS_COORD_ORIGIN, + ureg->property_fs_coord_origin); + } + + if (ureg->property_fs_coord_pixel_center) { + assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); + + emit_property(ureg, + TGSI_PROPERTY_FS_COORD_PIXEL_CENTER, + ureg->property_fs_coord_pixel_center); + } + if (ureg->processor == TGSI_PROCESSOR_VERTEX) { for (i = 0; i < UREG_MAX_INPUT; i++) { if (ureg->vs_inputs[i/32] & (1 << (i%32))) { @@ -1152,13 +1282,29 @@ static void emit_decls( struct ureg_program *ureg ) ureg->sampler[i].Index, 1 ); } - if (ureg->nr_constant_ranges) { - for (i = 0; i < ureg->nr_constant_ranges; i++) - emit_decl_range( ureg, - TGSI_FILE_CONSTANT, - ureg->constant_range[i].first, - (ureg->constant_range[i].last + 1 - - ureg->constant_range[i].first) ); + if (ureg->const_decls.nr_constant_ranges) { + for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) { + emit_decl_range(ureg, + TGSI_FILE_CONSTANT, + ureg->const_decls.constant_range[i].first, + ureg->const_decls.constant_range[i].last - ureg->const_decls.constant_range[i].first + 1); + } + } + + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + struct const_decl *decl = &ureg->const_decls2D[i]; + + if (decl->nr_constant_ranges) { + uint j; + + for (j = 0; j < decl->nr_constant_ranges; j++) { + emit_decl_range2D(ureg, + TGSI_FILE_CONSTANT, + decl->constant_range[j].first, + decl->constant_range[j].last, + i); + } + } } if (ureg->nr_temps) { @@ -1314,6 +1460,8 @@ struct ureg_program *ureg_create( unsigned processor ) ureg->processor = processor; ureg->property_gs_input_prim = ~0; + ureg->property_gs_output_prim = ~0; + ureg->property_gs_max_vertices = ~0; return ureg; } diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h index 03eaf24854..e25f35c6dc 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h @@ -52,9 +52,10 @@ struct ureg_src unsigned Absolute : 1; /* BOOL */ unsigned Negate : 1; /* BOOL */ int Index : 16; /* SINT */ + unsigned IndirectFile : 4; /* TGSI_FILE_ */ int IndirectIndex : 16; /* SINT */ - int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ - int DimensionIndex : 16; /* SINT */ + unsigned IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ + int DimensionIndex : 16; /* SINT */ }; /* Very similar to a tgsi_dst_register, removing unsupported fields @@ -125,8 +126,23 @@ ureg_create_shader_and_destroy( struct ureg_program *p, void ureg_property_gs_input_prim(struct ureg_program *ureg, - unsigned gs_input_prim); + unsigned input_prim); + +void +ureg_property_gs_output_prim(struct ureg_program *ureg, + unsigned output_prim); +void +ureg_property_gs_max_vertices(struct ureg_program *ureg, + unsigned max_vertices); + +void +ureg_property_fs_coord_origin(struct ureg_program *ureg, + unsigned fs_coord_origin); + +void +ureg_property_fs_coord_pixel_center(struct ureg_program *ureg, + unsigned fs_coord_pixel_center); /*********************************************************************** * Build shader declarations: @@ -168,10 +184,21 @@ ureg_DECL_immediate_uint( struct ureg_program *, unsigned nr ); struct ureg_src +ureg_DECL_immediate_block_uint( struct ureg_program *, + const unsigned *v, + unsigned nr ); + +struct ureg_src ureg_DECL_immediate_int( struct ureg_program *, const int *v, unsigned nr ); +void +ureg_DECL_constant2D(struct ureg_program *ureg, + unsigned first, + unsigned last, + unsigned index2D); + struct ureg_src ureg_DECL_constant( struct ureg_program *, unsigned index ); @@ -768,8 +795,9 @@ static INLINE struct ureg_src ureg_src_indirect( struct ureg_src reg, struct ureg_src addr ) { assert(reg.File != TGSI_FILE_NULL); - assert(addr.File == TGSI_FILE_ADDRESS); + assert(addr.File == TGSI_FILE_ADDRESS || addr.File == TGSI_FILE_TEMPORARY); reg.Indirect = 1; + reg.IndirectFile = addr.File; reg.IndirectIndex = addr.Index; reg.IndirectSwizzle = addr.SwizzleX; return reg; @@ -789,6 +817,8 @@ ureg_dst( struct ureg_src src ) { struct ureg_dst dst; + assert(!src.Indirect || src.IndirectFile == TGSI_FILE_ADDRESS); + dst.File = src.File; dst.WriteMask = TGSI_WRITEMASK_XYZW; dst.Indirect = src.Indirect; @@ -807,6 +837,30 @@ ureg_dst( struct ureg_src src ) } static INLINE struct ureg_src +ureg_src_register(unsigned file, + unsigned index) +{ + struct ureg_src src; + + src.File = file; + src.SwizzleX = TGSI_SWIZZLE_X; + src.SwizzleY = TGSI_SWIZZLE_Y; + src.SwizzleZ = TGSI_SWIZZLE_Z; + src.SwizzleW = TGSI_SWIZZLE_W; + src.Indirect = 0; + src.IndirectFile = TGSI_FILE_NULL; + src.IndirectIndex = 0; + src.IndirectSwizzle = 0; + src.Absolute = 0; + src.Index = index; + src.Negate = 0; + src.Dimension = 0; + src.DimensionIndex = 0; + + return src; +} + +static INLINE struct ureg_src ureg_src( struct ureg_dst dst ) { struct ureg_src src; @@ -817,6 +871,7 @@ ureg_src( struct ureg_dst dst ) src.SwizzleZ = TGSI_SWIZZLE_Z; src.SwizzleW = TGSI_SWIZZLE_W; src.Indirect = dst.Indirect; + src.IndirectFile = TGSI_FILE_ADDRESS; src.IndirectIndex = dst.IndirectIndex; src.IndirectSwizzle = dst.IndirectSwizzle; src.Absolute = 0; @@ -863,6 +918,7 @@ ureg_src_undef( void ) src.SwizzleZ = 0; src.SwizzleW = 0; src.Indirect = 0; + src.IndirectFile = TGSI_FILE_NULL; src.IndirectIndex = 0; src.IndirectSwizzle = 0; src.Absolute = 0; diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.c b/src/gallium/auxiliary/tgsi/tgsi_util.c index f4ca9e21ed..0a7e4105a8 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_util.c +++ b/src/gallium/auxiliary/tgsi/tgsi_util.c @@ -28,7 +28,6 @@ #include "util/u_debug.h" #include "pipe/p_shader_tokens.h" #include "tgsi_parse.h" -#include "tgsi_build.h" #include "tgsi_util.h" union pointer_hack diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 3f74e2aa8b..eb63bec7b5 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -92,7 +92,7 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso) /* disabled blending/masking */ memset(&ctx->blend, 0, sizeof(ctx->blend)); - ctx->blend.colormask = PIPE_MASK_RGBA; + ctx->blend.rt[0].colormask = PIPE_MASK_RGBA; /* no-op depth/stencil/alpha */ memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil)); @@ -226,8 +226,8 @@ setup_vertex_data_tex(struct blit_state *ctx, offset = get_next_slot( ctx ); - pipe_buffer_write(ctx->pipe->screen, ctx->vbuf, - offset, sizeof(ctx->vertices), ctx->vertices); + pipe_buffer_write_nooverlap(ctx->pipe->screen, ctx->vbuf, + offset, sizeof(ctx->vertices), ctx->vertices); return offset; } @@ -262,6 +262,10 @@ regions_overlap(int srcX0, int srcY0, * Copy pixel block from src surface to dst surface. * Overlapping regions are acceptable. * Flipping and stretching are supported. + * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR + * \param writemask controls which channels in the dest surface are sourced + * from the src surface. Disabled channels are sourced + * from (0,0,0,1). * XXX what about clipping??? * XXX need some control over blitting Z and/or stencil. */ diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index 249a0375fc..935e11c5d8 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -125,7 +125,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) memset(&blend, 0, sizeof(blend)); ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend); - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].colormask = PIPE_MASK_RGBA; ctx->blend_write_color = pipe->create_blend_state(pipe, &blend); /* depth stencil alpha state objects */ diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index 76023794dc..8611231ed7 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -1287,7 +1287,7 @@ util_create_gen_mipmap(struct pipe_context *pipe, /* disabled blending/masking */ memset(&ctx->blend, 0, sizeof(ctx->blend)); - ctx->blend.colormask = PIPE_MASK_RGBA; + ctx->blend.rt[0].colormask = PIPE_MASK_RGBA; /* no-op depth/stencil/alpha */ memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil)); @@ -1411,8 +1411,8 @@ set_vertex_data(struct gen_mipmap_state *ctx, offset = get_next_slot( ctx ); - pipe_buffer_write(ctx->pipe->screen, ctx->vbuf, - offset, sizeof(ctx->vertices), ctx->vertices); + pipe_buffer_write_nooverlap(ctx->pipe->screen, ctx->vbuf, + offset, sizeof(ctx->vertices), ctx->vertices); return offset; } diff --git a/src/gallium/auxiliary/util/u_surface.c b/src/gallium/auxiliary/util/u_surface.c index f66376ad75..70de140ec9 100644 --- a/src/gallium/auxiliary/util/u_surface.c +++ b/src/gallium/auxiliary/util/u_surface.c @@ -37,7 +37,6 @@ #include "pipe/p_defines.h" #include "util/u_memory.h" -#include "util/u_format.h" #include "util/u_surface.h" diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c index f9936eb1cb..c25e1e52e9 100644 --- a/src/gallium/auxiliary/util/u_tile.c +++ b/src/gallium/auxiliary/util/u_tile.c @@ -390,7 +390,7 @@ a4r4g4b4_put_tile_rgba(ushort *dst, g >>= 4; b >>= 4; a >>= 4; - *dst++ = (a << 12) | (r << 16) | (g << 4) | b; + *dst++ = (a << 12) | (r << 8) | (g << 4) | b; } p += src_stride; } diff --git a/src/gallium/auxiliary/util/u_upload_mgr.c b/src/gallium/auxiliary/util/u_upload_mgr.c index 975ee89c45..55a65375c8 100644 --- a/src/gallium/auxiliary/util/u_upload_mgr.c +++ b/src/gallium/auxiliary/util/u_upload_mgr.c @@ -85,7 +85,9 @@ my_buffer_write(struct pipe_screen *screen, map = pipe_buffer_map_range(screen, buf, offset, size, PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_FLUSH_EXPLICIT); + PIPE_BUFFER_USAGE_FLUSH_EXPLICIT | + PIPE_BUFFER_USAGE_DISCARD | + PIPE_BUFFER_USAGE_UNSYNCHRONIZED); if (map == NULL) return PIPE_ERROR_OUT_OF_MEMORY; diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst index d394f5b4f1..a7669575b9 100644 --- a/src/gallium/docs/source/context.rst +++ b/src/gallium/docs/source/context.rst @@ -54,7 +54,10 @@ objects. They all follow simple, one-method binding calls, e.g. * ``set_blend_color`` * ``set_clip_state`` * ``set_polygon_stipple`` -* ``set_scissor_state`` +* ``set_scissor_state`` sets the bounds for the scissor test, which culls + pixels before blending to render targets. If the :ref:`Rasterizer` does + not have the scissor test enabled, then the scissor bounds never need to + be set since they will not be used. * ``set_viewport_state`` * ``set_vertex_elements`` @@ -145,9 +148,51 @@ draws. Queries may be nested, though no state tracker currently exercises this. Queries can be created with ``create_query`` and deleted with -``destroy_query``. To enable a query, use ``begin_query``, and when finished, -use ``end_query`` to stop the query. Finally, ``get_query_result`` is used -to retrieve the results. +``destroy_query``. To start a query, use ``begin_query``, and when finished, +use ``end_query`` to end the query. + +``get_query_result`` is used to retrieve the results of a query. If +the ``wait`` parameter is TRUE, then the ``get_query_result`` call +will block until the results of the query are ready (and TRUE will be +returned). Otherwise, if the ``wait`` parameter is FALSE, the call +will not block and the return value will be TRUE if the query has +completed or FALSE otherwise. + +A common type of query is the occlusion query which counts the number of +fragments/pixels which are written to the framebuffer (and not culled by +Z/stencil/alpha testing or shader KILL instructions). + + +Conditional Rendering +^^^^^^^^^^^^^^^^^^^^^ + +A drawing command can be skipped depending on the outcome of a query +(typically an occlusion query). The ``render_condition`` function specifies +the query which should be checked prior to rendering anything. + +If ``render_condition`` is called with ``query`` = NULL, conditional +rendering is disabled and drawing takes place normally. + +If ``render_condition`` is called with a non-null ``query`` subsequent +drawing commands will be predicated on the outcome of the query. If +the query result is zero subsequent drawing commands will be skipped. + +If ``mode`` is PIPE_RENDER_COND_WAIT the driver will wait for the +query to complete before deciding whether to render. + +If ``mode`` is PIPE_RENDER_COND_NO_WAIT and the query has not yet +completed, the drawing command will be executed normally. If the query +has completed, drawing will be predicated on the outcome of the query. + +If ``mode`` is PIPE_RENDER_COND_BY_REGION_WAIT or +PIPE_RENDER_COND_BY_REGION_NO_WAIT rendering will be predicated as above +for the non-REGION modes but in the case that an occulusion query returns +a non-zero result, regions which were occluded may be ommitted by subsequent +drawing commands. This can result in better performance with some GPUs. +Normally, if the occlusion query returned a non-zero result subsequent +drawing happens normally so fragments may be generated, shaded and +processed even where they're known to be obscured. + Flushing ^^^^^^^^ diff --git a/src/gallium/docs/source/cso/blend.rst b/src/gallium/docs/source/cso/blend.rst index fd9e4a1e2d..55c0f32885 100644 --- a/src/gallium/docs/source/cso/blend.rst +++ b/src/gallium/docs/source/cso/blend.rst @@ -6,9 +6,50 @@ Blend This state controls blending of the final fragments into the target rendering buffers. -XXX it is unresolved what behavior should result if blend_enable is off. +Blend Factors +------------- + +The blend factors largely follow the same pattern as their counterparts +in other modern and legacy drawing APIs. + +XXX blurb about dual-source blends Members ------- -XXX undocumented members +independent_blend_enable + If enabled, blend state is different for each render target, and + for each render target set in the respective member of the rt array. + If disabled, blend state is the same for all render targets, and only + the first member of the rt array contains valid data. +logicop_enable + Enables logic ops. Cannot be enabled at the same time as blending, and + is always the same for all render targets. +logicop_func + The logic operation to use if logic ops are enabled. One of PIPE_LOGICOP. +dither + Whether dithering is enabled. +rt + Contains the per-rendertarget blend state. + +Per-rendertarget Members +------------------------ + +blend_enable + If blending is enabled, perform a blend calculation according to blend + functions and source/destination factors. Otherwise, the incoming fragment + color gets passed unmodified (but colormask still applies). +rgb_func + The blend function to use for rgb channels. One of PIPE_BLEND. +rgb_src_factor + The blend source factor to use for rgb channels. One of PIPE_BLENDFACTOR. +rgb_dst_factor + The blend destination factor to use for rgb channels. One of PIPE_BLENDFACTOR. +alpha_func + The blend function to use for the alpha channel. One of PIPE_BLEND. +alpha_src_factor + The blend source factor to use for the alpha channel. One of PIPE_BLENDFACTOR. +alpha_dst_factor + The blend destination factor to use for alpha channel. One of PIPE_BLENDFACTOR. +colormask + Bitmask of which channels to write. Combination of PIPE_MASK bits. diff --git a/src/gallium/docs/source/cso/rasterizer.rst b/src/gallium/docs/source/cso/rasterizer.rst index 4d8e1708e7..bfa4a1170a 100644 --- a/src/gallium/docs/source/cso/rasterizer.rst +++ b/src/gallium/docs/source/cso/rasterizer.rst @@ -7,32 +7,69 @@ The rasterizer state controls the rendering of points, lines and triangles. Attributes include polygon culling state, line width, line stipple, multisample state, scissoring and flat/smooth shading. - Members ------- +bypass_vs_clip_and_viewport +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Whether the entire TCL pipeline should be bypassed. This implies that +vertices are pre-transformed for the viewport, and will not be run +through the vertex shader. + +.. note:: + + Implementations may still clip away vertices that are not in the viewport + when this is set. + flatshade - If set, the provoking vertex of each polygon is used to determine the - color of the entire polygon. If not set, fragment colors will be - interpolated between the vertex colors. - Note that this is separate from the fragment shader input attributes - CONSTANT, LINEAR and PERSPECTIVE. We need the flatshade state at +^^^^^^^^^ + +If set, the provoking vertex of each polygon is used to determine the color +of the entire polygon. If not set, fragment colors will be interpolated +between the vertex colors. + +The actual interpolated shading algorithm is obviously +implementation-dependent, but will usually be Gourard for most hardware. + +.. note:: + + This is separate from the fragment shader input attributes + CONSTANT, LINEAR and PERSPECTIVE. The flatshade state is needed at clipping time to determine how to set the color of new vertices. - Also note that the draw module can implement flat shading by copying - the provoking vertex color to all the other vertices in the primitive. + + :ref:`Draw` can implement flat shading by copying the provoking vertex + color to all the other vertices in the primitive. flatshade_first - Whether the first vertex should be the provoking vertex, for most - primitives. If not set, the last vertex is the provoking vertex. +^^^^^^^^^^^^^^^ + +Whether the first vertex should be the provoking vertex, for most primitives. +If not set, the last vertex is the provoking vertex. + +There are several important exceptions to the specification of this rule. + +* ``PIPE_PRIMITIVE_POLYGON``: The provoking vertex is always the first + vertex. If the caller wishes to change the provoking vertex, they merely + need to rotate the vertices themselves. +* ``PIPE_PRIMITIVE_QUAD``, ``PIPE_PRIMITIVE_QUAD_STRIP``: This option has no + effect; the provoking vertex is always the last vertex. +* ``PIPE_PRIMITIVE_TRIANGLE_FAN``: When set, the provoking vertex is the + second vertex, not the first. This permits each segment of the fan to have + a different color. + +Other Members +^^^^^^^^^^^^^ light_twoside - If set, there are per-vertex back-facing colors. The draw module + If set, there are per-vertex back-facing colors. :ref:`Draw` uses this state along with the front/back information to set the final vertex colors prior to rasterization. front_winding Indicates the window order of front-facing polygons, either PIPE_WINDING_CW or PIPE_WINDING_CCW + cull_mode Indicates which polygons to cull, either PIPE_WINDING_NONE (cull no polygons), PIPE_WINDING_CW (cull clockwise-winding polygons), @@ -68,7 +105,7 @@ line_stipple_enable line_stipple_pattern 16-bit bitfield of on/off flags, used to pattern the line stipple. line_stipple_factor - When drawinga stippled line, each bit in the stipple pattern is + When drawing a stippled line, each bit in the stipple pattern is repeated N times, where N = line_stipple_factor + 1. line_last_pixel Controls whether the last pixel in a line is drawn or not. OpenGL @@ -96,7 +133,7 @@ sprite_coord_mode lower left vertex will have coordinate (0,0,0,1). For PIPE_SPRITE_COORD_UPPER_LEFT, the upper-left vertex will have coordinate (0,0,0,1). - This state is needed by the 'draw' module because that's where each + This state is needed by :ref:`Draw` because that's where each point vertex is converted into four quad vertices. There's no other place to emit the new vertex texture coordinates which are required for sprite rendering. @@ -108,45 +145,9 @@ scissor Whether the scissor test is enabled. multisample - Whether :ref:`MSAA` is enabled. - -bypass_vs_clip_and_viewport - Whether the entire TCL pipeline should be bypassed. This implies that - vertices are pre-transformed for the viewport, and will not be run - through the vertex shader. Note that implementations may still clip away - vertices that are not in the viewport. + Whether :term:`MSAA` is enabled. gl_rasterization_rules Whether the rasterizer should use (0.5, 0.5) pixel centers. When not set, the rasterizer will use (0, 0) for pixel centers. - -Notes ------ - -flatshade -^^^^^^^^^ - -The actual interpolated shading algorithm is obviously -implementation-dependent, but will usually be Gourard for most hardware. - -bypass_vs_clip_and_viewport -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -When set, this implies that vertices are pre-transformed for the viewport, and -will not be run through the vertex shader. Note that implementations may still -clip away vertices that are not visible. - -flatshade_first -^^^^^^^^^^^^^^^ - -There are several important exceptions to the specification of this rule. - -* ``PIPE_PRIMITIVE_POLYGON``: The provoking vertex is always the first - vertex. If the caller wishes to change the provoking vertex, they merely - need to rotate the vertices themselves. -* ``PIPE_PRIMITIVE_QUAD``, ``PIPE_PRIMITIVE_QUAD_STRIP``: This option has no - effect; the provoking vertex is always the last vertex. -* ``PIPE_PRIMITIVE_TRIANGLE_FAN``: When set, the provoking vertex is the - second vertex, not the first. This permits each segment of the fan to have - a different color. diff --git a/src/gallium/docs/source/cso/sampler.rst b/src/gallium/docs/source/cso/sampler.rst index e3f1757f57..8b67ca57f1 100644 --- a/src/gallium/docs/source/cso/sampler.rst +++ b/src/gallium/docs/source/cso/sampler.rst @@ -12,8 +12,6 @@ with the traditional (S, T, R, Q) notation. Members ------- -XXX undocumented compare_mode, compare_func - wrap_s How to wrap the S coordinate. One of PIPE_TEX_WRAP. wrap_t @@ -27,12 +25,18 @@ min_mip_filter PIPE_TEX_FILTER. mag_img_filter The filter to use when magnifying texels. One of PIPE_TEX_FILTER. +compare_mode + If set to PIPE_TEX_COMPARE_R_TO_TEXTURE, texture output is computed + according to compare_func, using r coord and the texture value as operands. + If set to PIPE_TEX_COMPARE_NONE, no comparison calculation is performed. +compare_func + How the comparison is computed. One of PIPE_FUNC. normalized_coords Whether the texture coordinates are normalized. If normalized, they will always be in [0, 1]. If not, they will be in the range of each dimension of the loaded texture. prefilter - XXX From the Doxy, "weird sampling state exposed by some APIs." Refine. + Cylindrical texcoord wrap enable per coord. Not exposed by most APIs. lod_bias The bias to apply to the level of detail. min_lod diff --git a/src/gallium/docs/source/distro.rst b/src/gallium/docs/source/distro.rst index a448203c6f..0ef9fe2645 100644 --- a/src/gallium/docs/source/distro.rst +++ b/src/gallium/docs/source/distro.rst @@ -61,10 +61,7 @@ VMWare SVGA ATI r300 ^^^^^^^^ -AMD/ATI r600 -^^^^^^^^^^^^ - -Highly experimental. +Testing-quality. Softpipe ^^^^^^^^ @@ -109,20 +106,31 @@ Auxiliary CSO Cache ^^^^^^^^^ +The CSO cache is used to accelerate preparation of state by saving +driver-specific state structures for later use. + +.. _draw: + Draw ^^^^ +Draw is a software :term:`TCL` pipeline for hardware that lacks vertex shaders +or other essential parts of pre-rasterization vertex preparation. + Gallivm ^^^^^^^ Indices ^^^^^^^ -Tool for translating or generating element indices for element-based -rendering. +Indices provides tools for translating or generating element indices for +use with element-based rendering. + +Pipe Buffer Managers +^^^^^^^^^^^^^^^^^^^^ -Pipe Buffer Manager -^^^^^^^^^^^^^^^^^^^ +Each of these managers provides various services to drivers that are not +fully utilizing a memory manager. Remote Debugger ^^^^^^^^^^^^^^^ @@ -133,7 +141,8 @@ Runtime Assembly Emission TGSI ^^^^ -Basic utilities for manipulating TGSI streams. +The TGSI auxiliary module provides basic utilities for manipulating TGSI +streams. Translate ^^^^^^^^^ diff --git a/src/gallium/docs/source/glossary.rst b/src/gallium/docs/source/glossary.rst index 6a9110ce78..0696cb5d27 100644 --- a/src/gallium/docs/source/glossary.rst +++ b/src/gallium/docs/source/glossary.rst @@ -8,3 +8,16 @@ Glossary Multi-Sampled Anti-Aliasing. A basic anti-aliasing technique that takes multiple samples of the depth buffer, and uses this information to smooth the edges of polygons. + + TCL + Transform, Clipping, & Lighting. The three stages of preparation in a + rasterizing pipeline prior to the actual rasterization of vertices into + fragments. + + NPOT + Non-power-of-two. Usually applied to textures which have at least one + dimension which is not a power of two. + + LOD + Level of Detail. Also spelled "LoD." The value that determines when the + switches between mipmaps occur during texture sampling. diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst index 9631e6967e..3e57a282fd 100644 --- a/src/gallium/docs/source/screen.rst +++ b/src/gallium/docs/source/screen.rst @@ -3,6 +3,160 @@ Screen A screen is an object representing the context-independent part of a device. +Useful Flags +------------ + +.. _pipe_cap: + +PIPE_CAP +^^^^^^^^ + +Pipe capabilities help expose hardware functionality not explicitly required +by Gallium. For floating-point values, use :ref:`get_paramf`, and for boolean +or integer values, use :ref:`get_param`. + +The integer capabilities: + +* ``MAX_TEXTURE_IMAGE_UNITS``: The maximum number of samplers available. +* ``NPOT_TEXTURES``: Whether :term:`NPOT` textures may have repeat modes, + normalized coordinates, and mipmaps. +* ``TWO_SIDED_STENCIL``: Whether the stencil test can also affect back-facing + polygons. +* ``GLSL``: Deprecated. +* ``DUAL_SOURCE_BLEND``: Whether dual-source blend factors are supported. See + :ref:`Blend` for more information. +* ``ANISOTROPIC_FILTER``: Whether textures can be filtered anisotropically. +* ``POINT_SPRITE``: Whether point sprites are available. +* ``MAX_RENDER_TARGETS``: The maximum number of render targets that may be + bound. +* ``OCCLUSION_QUERY``: Whether occlusion queries are available. +* ``TEXTURE_SHADOW_MAP``: XXX +* ``MAX_TEXTURE_2D_LEVELS``: The maximum number of mipmap levels available + for a 2D texture. +* ``MAX_TEXTURE_3D_LEVELS``: The maximum number of mipmap levels available + for a 3D texture. +* ``MAX_TEXTURE_CUBE_LEVELS``: The maximum number of mipmap levels available + for a cubemap. +* ``TEXTURE_MIRROR_CLAMP``: Whether mirrored texture coordinates with clamp + are supported. +* ``TEXTURE_MIRROR_REPEAT``: Whether mirrored repeating texture coordinates + are supported. +* ``MAX_VERTEX_TEXTURE_UNITS``: The maximum number of samplers addressable + inside the vertex shader. If this is 0, then the vertex shader cannot + sample textures. +* ``TGSI_CONT_SUPPORTED``: Whether the TGSI CONT opcode is supported. +* ``BLEND_EQUATION_SEPARATE``: Whether alpha blend equations may be different + from color blend equations, in :ref:`Blend` state. +* ``SM3``: Whether the vertex shader and fragment shader support equivalent + opcodes to the Shader Model 3 specification. XXX oh god this is horrible +* ``MAX_PREDICATE_REGISTERS``: XXX +* ``MAX_COMBINED_SAMPLERS``: The total number of samplers accessible from + the vertex and fragment shader, inclusive. +* ``MAX_CONST_BUFFERS``: Maximum number of constant buffers that can be bound + to any shader stage using ``set_constant_buffer``. If 0 or 1, the pipe will + only permit binding one constant buffer per shader, and the shaders will + not permit two-dimensional access to constants. +* ``MAX_CONST_BUFFER_SIZE``: Maximum byte size of a single constant buffer. +* ``INDEP_BLEND_ENABLE``: Whether per-rendertarget blend enabling and channel + masks are supported. If 0, then the first rendertarget's blend mask is + replicated across all MRTs. +* ``INDEP_BLEND_FUNC``: Whether per-rendertarget blend functions are + available. If 0, then the first rendertarget's blend functions affect all + MRTs. +* ``PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT``: Whether the TGSI property + FS_COORD_ORIGIN with value UPPER_LEFT is supported. +* ``PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT``: Whether the TGSI property + FS_COORD_ORIGIN with value LOWER_LEFT is supported. +* ``PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER``: Whether the TGSI + property FS_COORD_PIXEL_CENTER with value HALF_INTEGER is supported. +* ``PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER``: Whether the TGSI + property FS_COORD_PIXEL_CENTER with value INTEGER is supported. + +The floating-point capabilities: + +* ``MAX_LINE_WIDTH``: The maximum width of a regular line. +* ``MAX_LINE_WIDTH_AA``: The maximum width of a smoothed line. +* ``MAX_POINT_WIDTH``: The maximum width and height of a point. +* ``MAX_POINT_WIDTH_AA``: The maximum width and height of a smoothed point. +* ``MAX_TEXTURE_ANISOTROPY``: The maximum level of anisotropy that can be + applied to anisotropically filtered textures. +* ``MAX_TEXTURE_LOD_BIAS``: The maximum :term:`LOD` bias that may be applied + to filtered textures. +* ``GUARD_BAND_LEFT``, ``GUARD_BAND_TOP``, ``GUARD_BAND_RIGHT``, + ``GUARD_BAND_BOTTOM``: XXX + +XXX Is there a better home for this? vvv + +If 0 is returned, the driver is not aware of multiple constant buffers, +supports binding of only one constant buffer, and does not support +two-dimensional CONST register file access in TGSI shaders. + +If a value greater than 0 is returned, the driver can have multiple +constant buffers bound to shader stages. The CONST register file can +be accessed with two-dimensional indices, like in the example below. + +DCL CONST[0][0..7] # declare first 8 vectors of constbuf 0 +DCL CONST[3][0] # declare first vector of constbuf 3 +MOV OUT[0], CONST[0][3] # copy vector 3 of constbuf 0 + +For backwards compatibility, one-dimensional access to CONST register +file is still supported. In that case, the constbuf index is assumed +to be 0. + +.. _pipe_buffer_usage: + +PIPE_BUFFER_USAGE +^^^^^^^^^^^^^^^^^ + +These flags control buffer creation. Buffers may only have one role, so +care should be taken to not allocate a buffer with the wrong usage. + +* ``PIXEL``: This is the flag to use for all textures. +* ``VERTEX``: A vertex buffer. +* ``INDEX``: An element buffer. +* ``CONSTANT``: A buffer of shader constants. + +Buffers are inevitably abstracting the pipe's underlying memory management, +so many of their usage flags can be used to direct the way the buffer is +handled. + +* ``CPU_READ``, ``CPU_WRITE``: Whether the user will map and, in the case of + the latter, write to, the buffer. The convenience flag ``CPU_READ_WRITE`` is + available to signify a read/write buffer. +* ``GPU_READ``, ``GPU_WRITE``: Whether the driver will internally need to + read from or write to the buffer. The latter will only happen if the buffer + is made into a render target. +* ``DISCARD``: When set on a map, the contents of the map will be discarded + beforehand. Cannot be used with ``CPU_READ``. +* ``DONTBLOCK``: When set on a map, the map will fail if the buffer cannot be + mapped immediately. +* ``UNSYNCHRONIZED``: When set on a map, any outstanding operations on the + buffer will be ignored. The interaction of any writes to the map and any + operations pending with the buffer are undefined. Cannot be used with + ``CPU_READ``. +* ``FLUSH_EXPLICIT``: When set on a map, written ranges of the map require + explicit flushes using :ref:`buffer_flush_mapped_range`. Requires + ``CPU_WRITE``. + +.. _pipe_texture_usage: + +PIPE_TEXTURE_USAGE +^^^^^^^^^^^^^^^^^^ + +These flags determine the possible roles a texture may be used for during its +lifetime. Texture usage flags are cumulative and may be combined to create a +texture that can be used as multiple things. + +* ``RENDER_TARGET``: A colorbuffer or pixelbuffer. +* ``DISPLAY_TARGET``: A sharable buffer that can be given to another process. +* ``PRIMARY``: A frontbuffer or scanout buffer. +* ``DEPTH_STENCIL``: A depthbuffer, stencilbuffer, or Z buffer. Gallium does + not explicitly provide for stencil-only buffers, so any stencilbuffer + validated here is implicitly also a depthbuffer. +* ``SAMPLER``: A texture that may be sampled from in a fragment or vertex + shader. +* ``DYNAMIC``: A texture that will be mapped frequently. + Methods ------- @@ -18,22 +172,87 @@ get_vendor Returns the screen vendor. +.. _get_param: + get_param ^^^^^^^^^ Get an integer/boolean screen parameter. +**param** is one of the :ref:`PIPE_CAP` names. + +.. _get_paramf: + get_paramf ^^^^^^^^^^ Get a floating-point screen parameter. +**param** is one of the :ref:`PIPE_CAP` names. + is_format_supported ^^^^^^^^^^^^^^^^^^^ See if a format can be used in a specific manner. +**usage** is a bitmask of :ref:`PIPE_TEXTURE_USAGE` flags. + +Returns TRUE if all usages can be satisfied. + +.. note:: + + ``PIPE_TEXTURE_USAGE_DYNAMIC`` is not a valid usage. + +.. _texture_create: + texture_create ^^^^^^^^^^^^^^ -Given a template of texture setup, create a BO-backed texture. +Given a template of texture setup, create a buffer and texture. + +texture_blanket +^^^^^^^^^^^^^^^ + +Like :ref:`texture_create`, but use a supplied buffer instead of creating a +new one. + +texture_destroy +^^^^^^^^^^^^^^^ + +Destroy a texture. The buffer backing the texture is destroyed if it has no +more references. + +buffer_map +^^^^^^^^^^ + +Map a buffer into memory. + +**usage** is a bitmask of :ref:`PIPE_TEXTURE_USAGE` flags. + +Returns a pointer to the map, or NULL if the mapping failed. + +buffer_map_range +^^^^^^^^^^^^^^^^ + +Map a range of a buffer into memory. + +The returned map is always relative to the beginning of the buffer, not the +beginning of the mapped range. + +.. _buffer_flush_mapped_range: + +buffer_flush_mapped_range +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Flush a range of mapped memory into a buffer. + +The buffer must have been mapped with ``PIPE_BUFFER_USAGE_FLUSH_EXPLICIT``. + +**usage** is a bitmask of :ref:`PIPE_TEXTURE_USAGE` flags. + +buffer_unmap +^^^^^^^^^^^^ + +Unmap a buffer from memory. + +Any pointers into the map should be considered invalid and discarded. diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst index ebee4902b0..3e702ceeda 100644 --- a/src/gallium/docs/source/tgsi.rst +++ b/src/gallium/docs/source/tgsi.rst @@ -516,8 +516,11 @@ SEQ - Set On Equal .. math:: dst.x = (src0.x == src1.x) ? 1 : 0 + dst.y = (src0.y == src1.y) ? 1 : 0 + dst.z = (src0.z == src1.z) ? 1 : 0 + dst.w = (src0.w == src1.w) ? 1 : 0 @@ -526,8 +529,11 @@ SFL - Set On False .. math:: dst.x = 0 + dst.y = 0 + dst.z = 0 + dst.w = 0 Considered for removal. @@ -537,8 +543,11 @@ SGT - Set On Greater Than .. math:: dst.x = (src0.x > src1.x) ? 1 : 0 + dst.y = (src0.y > src1.y) ? 1 : 0 + dst.z = (src0.z > src1.z) ? 1 : 0 + dst.w = (src0.w > src1.w) ? 1 : 0 @@ -560,8 +569,11 @@ SLE - Set On Less Equal Than .. math:: dst.x = (src0.x <= src1.x) ? 1 : 0 + dst.y = (src0.y <= src1.y) ? 1 : 0 + dst.z = (src0.z <= src1.z) ? 1 : 0 + dst.w = (src0.w <= src1.w) ? 1 : 0 @@ -570,8 +582,11 @@ SNE - Set On Not Equal .. math:: dst.x = (src0.x != src1.x) ? 1 : 0 + dst.y = (src0.y != src1.y) ? 1 : 0 + dst.z = (src0.z != src1.z) ? 1 : 0 + dst.w = (src0.w != src1.w) ? 1 : 0 @@ -580,8 +595,11 @@ STR - Set On True .. math:: dst.x = 1 + dst.y = 1 + dst.z = 1 + dst.w = 1 @@ -629,8 +647,11 @@ X2D - 2D Coordinate Transformation .. math:: dst.x = src0.x + src1.x \times src2.x + src1.y \times src2.y + dst.y = src0.y + src1.x \times src2.z + src1.y \times src2.w + dst.z = src0.x + src1.x \times src2.x + src1.y \times src2.y + dst.w = src0.y + src1.x \times src2.z + src1.y \times src2.w Considered for removal. @@ -979,13 +1000,13 @@ XOR - Bitwise Xor .. math:: - dst.x = src0.x ^ src1.x + dst.x = src0.x \oplus src1.x - dst.y = src0.y ^ src1.y + dst.y = src0.y \oplus src1.y - dst.z = src0.z ^ src1.z + dst.z = src0.z \oplus src1.z - dst.w = src0.w ^ src1.w + dst.w = src0.w \oplus src1.w SAD - Sum Of Absolute Differences @@ -1090,6 +1111,117 @@ BREAKC - Break Conditional TBD +Double Opcodes +^^^^^^^^^^^^^^^ + +DADD - Add Double + +.. math:: + + dst.xy = src0.xy + src1.xy + + dst.zw = src0.zw + src1.zw + + +DDIV - Divide Double + +.. math:: + + dst.xy = src0.xy / src1.xy + + dst.zw = src0.zw / src1.zw + +DSEQ - Set Double on Equal + +.. math:: + + dst.xy = src0.xy == src1.xy ? 1.0F : 0.0F + + dst.zw = src0.zw == src1.zw ? 1.0F : 0.0F + +DSLT - Set Double on Less than + +.. math:: + + dst.xy = src0.xy < src1.xy ? 1.0F : 0.0F + + dst.zw = src0.zw < src1.zw ? 1.0F : 0.0F + +DFRAC - Double Fraction + +.. math:: + + dst.xy = src.xy - \lfloor src.xy\rfloor + + dst.zw = src.zw - \lfloor src.zw\rfloor + + +DFRACEXP - Convert Double Number to Fractional and Integral Components + +.. math:: + + dst0.xy = frexp(src.xy, dst1.xy) + + dst0.zw = frexp(src.zw, dst1.zw) + +DLDEXP - Multiple Double Number by Integral Power of 2 + +.. math:: + + dst.xy = ldexp(src0.xy, src1.xy) + + dst.zw = ldexp(src0.zw, src1.zw) + +DMIN - Minimum Double + +.. math:: + + dst.xy = min(src0.xy, src1.xy) + + dst.zw = min(src0.zw, src1.zw) + +DMAX - Maximum Double + +.. math:: + + dst.xy = max(src0.xy, src1.xy) + + dst.zw = max(src0.zw, src1.zw) + +DMUL - Multiply Double + +.. math:: + + dst.xy = src0.xy \times src1.xy + + dst.zw = src0.zw \times src1.zw + + +DMAD - Multiply And Add Doubles + +.. math:: + + dst.xy = src0.xy \times src1.xy + src2.xy + + dst.zw = src0.zw \times src1.zw + src2.zw + + +DRCP - Reciprocal Double + +.. math:: + + dst.xy = \frac{1}{src.xy} + + dst.zw = \frac{1}{src.zw} + +DSQRT - Square root double + +.. math:: + + dst.xy = \sqrt{src.xy} + + dst.zw = \sqrt{src.zw} + Explanation of symbols used ------------------------------ @@ -1187,9 +1319,8 @@ are the Cartesian coordinates, and ``w`` is the homogenous coordinate and used for the perspective divide, if enabled. As a vertex shader output, position should be scaled to the viewport. When -used in fragment shaders, position will --- - -XXX --- wait a minute. Should position be in [0,1] for x and y? +used in fragment shaders, position will be in window coordinates. The convention +used depends on the FS_COORD_ORIGIN and FS_COORD_PIXEL_CENTER properties. XXX additionally, is there a way to configure the perspective divide? it's accelerated on most chipsets AFAIK... @@ -1268,3 +1399,45 @@ TGSI_SEMANTIC_EDGEFLAG """""""""""""""""""""" XXX no clue + + +Properties +^^^^^^^^^^^^^^^^^^^^^^^^ + + + Properties are general directives that apply to the whole TGSI program. + +FS_COORD_ORIGIN +""""""""""""""" + +Specifies the fragment shader TGSI_SEMANTIC_POSITION coordinate origin. +The default value is UPPER_LEFT. + +If UPPER_LEFT, the position will be (0,0) at the upper left corner and +increase downward and rightward. +If LOWER_LEFT, the position will be (0,0) at the lower left corner and +increase upward and rightward. + +OpenGL defaults to LOWER_LEFT, and is configurable with the +GL_ARB_fragment_coord_conventions extension. + +DirectX 9/10 use UPPER_LEFT. + +FS_COORD_PIXEL_CENTER +""""""""""""""""""""" + +Specifies the fragment shader TGSI_SEMANTIC_POSITION pixel center convention. +The default value is HALF_INTEGER. + +If HALF_INTEGER, the fractionary part of the position will be 0.5 +If INTEGER, the fractionary part of the position will be 0.0 + +Note that this does not affect the set of fragments generated by +rasterization, which is instead controlled by gl_rasterization_rules in the +rasterizer. + +OpenGL defaults to HALF_INTEGER, and is configurable with the +GL_ARB_fragment_coord_conventions extension. + +DirectX 9 uses INTEGER. +DirectX 10 uses HALF_INTEGER. diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c index 0a4da8ecc8..c674d0be63 100644 --- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c +++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c @@ -59,7 +59,7 @@ cell_map_constant_buffers(struct cell_context *sp) } } - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX, + draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX, 0, sp->mapped_constants[PIPE_SHADER_VERTEX], sp->constants[PIPE_SHADER_VERTEX]->size); } diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c index 66d4b3b6a3..0dab34075d 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c @@ -408,7 +408,7 @@ gen_blend(const struct pipe_blend_state *blend, int one_reg = -1; int constR_reg = -1, constG_reg = -1, constB_reg = -1, constA_reg = -1; - ASSERT(blend->blend_enable); + ASSERT(blend->rt[0].blend_enable); /* packed RGBA -> float colors */ unpack_colors(f, color_format, fbRGBA_reg, @@ -420,7 +420,7 @@ gen_blend(const struct pipe_blend_state *blend, * because in some cases (like PIPE_BLENDFACTOR_ONE and * PIPE_BLENDFACTOR_ZERO) we can avoid doing unnecessary math. */ - switch (blend->rgb_src_factor) { + switch (blend->rt[0].rgb_src_factor) { case PIPE_BLENDFACTOR_ONE: /* factors = (1,1,1), so term = (R,G,B) */ spe_move(f, term1R_reg, fragR_reg); @@ -574,7 +574,7 @@ gen_blend(const struct pipe_blend_state *blend, * the full term A*factor, not just the factor itself, because * in many cases we can avoid doing unnecessary multiplies. */ - switch (blend->alpha_src_factor) { + switch (blend->rt[0].alpha_src_factor) { case PIPE_BLENDFACTOR_ZERO: /* factor = 0, so term = 0 */ spe_load_float(f, term1A_reg, 0.0f); @@ -648,7 +648,7 @@ gen_blend(const struct pipe_blend_state *blend, * the full term (Rfb,Gfb,Bfb)*(factor), not just the factor itself, because * in many cases we can avoid doing unnecessary multiplies. */ - switch (blend->rgb_dst_factor) { + switch (blend->rt[0].rgb_dst_factor) { case PIPE_BLENDFACTOR_ONE: /* factors = (1,1,1), so term = (Rfb,Gfb,Bfb) */ spe_move(f, term2R_reg, fbR_reg); @@ -786,7 +786,7 @@ gen_blend(const struct pipe_blend_state *blend, * the full term Afb*factor, not just the factor itself, because * in many cases we can avoid doing unnecessary multiplies. */ - switch (blend->alpha_dst_factor) { + switch (blend->rt[0].alpha_dst_factor) { case PIPE_BLENDFACTOR_ONE: /* factor = 1, so term = Afb */ spe_move(f, term2A_reg, fbA_reg); @@ -858,7 +858,7 @@ gen_blend(const struct pipe_blend_state *blend, /* * Combine Src/Dest RGB terms as per the blend equation. */ - switch (blend->rgb_func) { + switch (blend->rt[0].rgb_func) { case PIPE_BLEND_ADD: spe_fa(f, fragR_reg, term1R_reg, term2R_reg); spe_fa(f, fragG_reg, term1G_reg, term2G_reg); @@ -891,7 +891,7 @@ gen_blend(const struct pipe_blend_state *blend, /* * Combine Src/Dest A term */ - switch (blend->alpha_func) { + switch (blend->rt[0].alpha_func) { case PIPE_BLEND_ADD: spe_fa(f, fragA_reg, term1A_reg, term2A_reg); break; @@ -2118,7 +2118,7 @@ cell_gen_fragment_function(struct cell_context *cell, spe_comment(f, 0, "Fetch quad colors from tile"); spe_lqx(f, fbRGBA_reg, color_tile_reg, quad_offset_reg); - if (blend->blend_enable) { + if (blend->rt[0].blend_enable) { spe_comment(f, 0, "Perform blending"); gen_blend(blend, blend_color, f, color_format, fragR_reg, fragG_reg, fragB_reg, fragA_reg, fbRGBA_reg); @@ -2143,9 +2143,9 @@ cell_gen_fragment_function(struct cell_context *cell, gen_logicop(blend, f, rgba_reg, fbRGBA_reg); } - if (blend->colormask != PIPE_MASK_RGBA) { + if (blend->rt[0].colormask != PIPE_MASK_RGBA) { spe_comment(f, 0, "Compute color mask"); - gen_colormask(f, blend->colormask, color_format, rgba_reg, fbRGBA_reg); + gen_colormask(f, blend->rt[0].colormask, color_format, rgba_reg, fbRGBA_reg); } /* Mix fragment colors with framebuffer colors using the quad/pixel mask: diff --git a/src/gallium/drivers/cell/ppu/cell_screen.c b/src/gallium/drivers/cell/ppu/cell_screen.c index d185c6b849..37b04396b3 100644 --- a/src/gallium/drivers/cell/ppu/cell_screen.c +++ b/src/gallium/drivers/cell/ppu/cell_screen.c @@ -86,6 +86,12 @@ cell_get_param(struct pipe_screen *screen, int param) return 0; /* XXX to do */ case PIPE_CAP_TGSI_CONT_SUPPORTED: return 1; + 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; default: return 0; } diff --git a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c index d97c22b2ef..21af7ed1c3 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c @@ -999,23 +999,23 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) /* Does the selected blend mode make use of the source / destination * color (RGB) blend factors? */ - boolean need_color_factor = b->blend_enable - && (b->rgb_func != PIPE_BLEND_MIN) - && (b->rgb_func != PIPE_BLEND_MAX); + boolean need_color_factor = b->rt[0].blend_enable + && (b->rt[0].rgb_func != PIPE_BLEND_MIN) + && (b->rt[0].rgb_func != PIPE_BLEND_MAX); /* Does the selected blend mode make use of the source / destination * alpha blend factors? */ - boolean need_alpha_factor = b->blend_enable - && (b->alpha_func != PIPE_BLEND_MIN) - && (b->alpha_func != PIPE_BLEND_MAX); + boolean need_alpha_factor = b->rt[0].blend_enable + && (b->rt[0].alpha_func != PIPE_BLEND_MIN) + && (b->rt[0].alpha_func != PIPE_BLEND_MAX); - if (b->blend_enable) { - sF[0] = b->rgb_src_factor; + if (b->rt[0].blend_enable) { + sF[0] = b->rt[0].rgb_src_factor; sF[1] = sF[0]; sF[2] = sF[0]; - switch (b->alpha_src_factor & 0x0f) { + switch (b->rt[0].alpha_src_factor & 0x0f) { case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: sF[3] = PIPE_BLENDFACTOR_ONE; break; @@ -1023,30 +1023,30 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) case PIPE_BLENDFACTOR_DST_COLOR: case PIPE_BLENDFACTOR_CONST_COLOR: case PIPE_BLENDFACTOR_SRC1_COLOR: - sF[3] = b->alpha_src_factor + 1; + sF[3] = b->rt[0].alpha_src_factor + 1; break; default: - sF[3] = b->alpha_src_factor; + sF[3] = b->rt[0].alpha_src_factor; } - dF[0] = b->rgb_dst_factor; + dF[0] = b->rt[0].rgb_dst_factor; dF[1] = dF[0]; dF[2] = dF[0]; - switch (b->alpha_dst_factor & 0x0f) { + switch (b->rt[0].alpha_dst_factor & 0x0f) { case PIPE_BLENDFACTOR_SRC_COLOR: case PIPE_BLENDFACTOR_DST_COLOR: case PIPE_BLENDFACTOR_CONST_COLOR: case PIPE_BLENDFACTOR_SRC1_COLOR: - dF[3] = b->alpha_dst_factor + 1; + dF[3] = b->rt[0].alpha_dst_factor + 1; break; default: - dF[3] = b->alpha_dst_factor; + dF[3] = b->rt[0].alpha_dst_factor; } - func[0] = b->rgb_func; + func[0] = b->rt[0].rgb_func; func[1] = func[0]; func[2] = func[0]; - func[3] = b->alpha_func; + func[3] = b->rt[0].alpha_func; } else { sF[0] = PIPE_BLENDFACTOR_ONE; sF[1] = PIPE_BLENDFACTOR_ONE; @@ -1067,7 +1067,7 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) /* If alpha writing is enabled and the alpha blend mode requires use of * the alpha factor, calculate the alpha factor. */ - if (((b->colormask & 8) != 0) && need_alpha_factor) { + if (((b->rt[0].colormask & 8) != 0) && need_alpha_factor) { src_factor[3] = emit_alpha_factor_calculation(f, sF[3], const_color[3], frag[3], pixel[3]); @@ -1091,8 +1091,8 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) src_factor[2] = dst_factor[3]; } else if (need_color_factor) { emit_color_factor_calculation(f, - b->rgb_src_factor, - b->colormask, + b->rt[0].rgb_src_factor, + b->rt[0].colormask, frag, pixel, const_color, src_factor); } @@ -1111,15 +1111,15 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) dst_factor[2] = src_factor[2]; } else if (need_color_factor) { emit_color_factor_calculation(f, - b->rgb_dst_factor, - b->colormask, + b->rt[0].rgb_dst_factor, + b->rt[0].colormask, frag, pixel, const_color, dst_factor); } for (i = 0; i < 4; ++i) { - if ((b->colormask & (1U << i)) != 0) { + if ((b->rt[0].colormask & (1U << i)) != 0) { emit_blend_calculation(f, func[i], sF[i], dF[i], frag[i], src_factor[i], @@ -1216,7 +1216,7 @@ cell_generate_logic_op(struct spe_function *f, /* Short-circuit the noop and invert cases. */ - if ((logic_op == PIPE_LOGICOP_NOOP) || (blend->colormask == 0)) { + if ((logic_op == PIPE_LOGICOP_NOOP) || (blend->rt[0].colormask == 0)) { spe_bi(f, 0, 0, 0); return; } else if (logic_op == PIPE_LOGICOP_INVERT) { diff --git a/src/gallium/drivers/cell/spu/spu_main.h b/src/gallium/drivers/cell/spu/spu_main.h index b18f4c22ef..a9d72f84d5 100644 --- a/src/gallium/drivers/cell/spu/spu_main.h +++ b/src/gallium/drivers/cell/spu/spu_main.h @@ -100,8 +100,10 @@ struct spu_framebuffer void *depth_start; /**< addr of depth surface in main memory */ enum pipe_format color_format; enum pipe_format depth_format; - uint width, height; /**< size in pixels */ - uint width_tiles, height_tiles; /**< width and height in tiles */ + uint width; /**< width in pixels */ + uint height; /**< height in pixels */ + uint width_tiles; /**< width in tiles */ + uint height_tiles; /**< width in tiles */ uint color_clear_value; uint depth_clear_value; @@ -116,15 +118,23 @@ PIPE_ALIGN_TYPE(16, struct spu_texture_level { void *start; - ushort width, height, depth; + ushort width; + ushort height; + ushort depth; ushort tiles_per_row; uint bytes_per_image; /** texcoord scale factors */ - vector float scale_s, scale_t, scale_r; + vector float scale_s; + vector float scale_t; + vector float scale_r; /** texcoord masks (if REPEAT then size-1, else ~0) */ - vector signed int mask_s, mask_t, mask_r; + vector signed int mask_s; + vector signed int mask_t; + vector signed int mask_r; /** texcoord clamp limits */ - vector signed int max_s, max_t, max_r; + vector signed int max_s; + vector signed int max_t; + vector signed int max_r; }); @@ -166,7 +176,8 @@ struct spu_global boolean read_depth_stencil; /** Current tiles' status */ - ubyte cur_ctile_status, cur_ztile_status; + ubyte cur_ctile_status; + ubyte cur_ztile_status; /** Status of all tiles in framebuffer */ PIPE_ALIGN_VAR(16) ubyte ctile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE]; diff --git a/src/gallium/drivers/i915/i915_clear.c b/src/gallium/drivers/i915/i915_clear.c index 90530f2826..0d0859f8f3 100644 --- a/src/gallium/drivers/i915/i915_clear.c +++ b/src/gallium/drivers/i915/i915_clear.c @@ -32,7 +32,6 @@ #include "util/u_clear.h" #include "i915_context.h" -#include "i915_state.h" /** diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index 89feeade75..a0c80d0228 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -29,12 +29,9 @@ #include "i915_state.h" #include "i915_screen.h" #include "i915_batch.h" -#include "i915_texture.h" -#include "i915_reg.h" #include "draw/draw_context.h" #include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" #include "pipe/p_inlines.h" #include "util/u_memory.h" #include "pipe/p_screen.h" @@ -84,7 +81,7 @@ i915_draw_range_elements(struct pipe_context *pipe, } - draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, + draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, i915->current.constants[PIPE_SHADER_VERTEX], (i915->current.num_user_constants[PIPE_SHADER_VERTEX] * 4 * sizeof(float))); diff --git a/src/gallium/drivers/i915/i915_debug.c b/src/gallium/drivers/i915/i915_debug.c index c6e6d6fd31..237654d26b 100644 --- a/src/gallium/drivers/i915/i915_debug.c +++ b/src/gallium/drivers/i915/i915_debug.c @@ -29,7 +29,6 @@ #include "i915_context.h" #include "i915_debug.h" #include "i915_batch.h" -#include "pipe/internal/p_winsys_screen.h" #include "util/u_debug.h" diff --git a/src/gallium/drivers/i915/i915_debug_fp.c b/src/gallium/drivers/i915/i915_debug_fp.c index 9c5b117b6d..f9c40d8a11 100644 --- a/src/gallium/drivers/i915/i915_debug_fp.c +++ b/src/gallium/drivers/i915/i915_debug_fp.c @@ -29,7 +29,6 @@ #include "i915_reg.h" #include "i915_debug.h" #include "pipe/internal/p_winsys_screen.h" -#include "util/u_memory.h" static void diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index d4ee8f5339..7b8d66b8aa 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -117,6 +117,12 @@ i915_get_param(struct pipe_screen *screen, int param) return 8; /* max 128x128x128 */ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 11; /* max 1024x1024 */ + 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; default: return 0; } diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index 0fab6e1bc3..23e4d6b993 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -30,7 +30,6 @@ #include "draw/draw_context.h" -#include "pipe/internal/p_winsys_screen.h" #include "pipe/p_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -38,7 +37,6 @@ #include "i915_context.h" #include "i915_reg.h" -#include "i915_state.h" #include "i915_state_inlines.h" #include "i915_fpc.h" @@ -105,13 +103,13 @@ i915_create_blend_state(struct pipe_context *pipe, struct i915_blend_state *cso_data = CALLOC_STRUCT( i915_blend_state ); { - unsigned eqRGB = blend->rgb_func; - unsigned srcRGB = blend->rgb_src_factor; - unsigned dstRGB = blend->rgb_dst_factor; + unsigned eqRGB = blend->rt[0].rgb_func; + unsigned srcRGB = blend->rt[0].rgb_src_factor; + unsigned dstRGB = blend->rt[0].rgb_dst_factor; - unsigned eqA = blend->alpha_func; - unsigned srcA = blend->alpha_src_factor; - unsigned dstA = blend->alpha_dst_factor; + unsigned eqA = blend->rt[0].alpha_func; + unsigned srcA = blend->rt[0].alpha_src_factor; + unsigned dstA = blend->rt[0].alpha_dst_factor; /* Special handling for MIN/MAX filter modes handled at * state_tracker level. @@ -148,22 +146,22 @@ i915_create_blend_state(struct pipe_context *pipe, if (blend->dither) cso_data->LIS5 |= S5_COLOR_DITHER_ENABLE; - if ((blend->colormask & PIPE_MASK_R) == 0) + if ((blend->rt[0].colormask & PIPE_MASK_R) == 0) cso_data->LIS5 |= S5_WRITEDISABLE_RED; - if ((blend->colormask & PIPE_MASK_G) == 0) + if ((blend->rt[0].colormask & PIPE_MASK_G) == 0) cso_data->LIS5 |= S5_WRITEDISABLE_GREEN; - if ((blend->colormask & PIPE_MASK_B) == 0) + if ((blend->rt[0].colormask & PIPE_MASK_B) == 0) cso_data->LIS5 |= S5_WRITEDISABLE_BLUE; - if ((blend->colormask & PIPE_MASK_A) == 0) + if ((blend->rt[0].colormask & PIPE_MASK_A) == 0) cso_data->LIS5 |= S5_WRITEDISABLE_ALPHA; - if (blend->blend_enable) { - unsigned funcRGB = blend->rgb_func; - unsigned srcRGB = blend->rgb_src_factor; - unsigned dstRGB = blend->rgb_dst_factor; + if (blend->rt[0].blend_enable) { + unsigned funcRGB = blend->rt[0].rgb_func; + unsigned srcRGB = blend->rt[0].rgb_src_factor; + unsigned dstRGB = blend->rt[0].rgb_dst_factor; cso_data->LIS6 |= (S6_CBUF_BLEND_ENABLE | SRC_BLND_FACT(i915_translate_blend_factor(srcRGB)) | diff --git a/src/gallium/drivers/i915/i915_state_derived.c b/src/gallium/drivers/i915/i915_state_derived.c index 03dd5091a6..f5b0e9f011 100644 --- a/src/gallium/drivers/i915/i915_state_derived.c +++ b/src/gallium/drivers/i915/i915_state_derived.c @@ -33,7 +33,6 @@ #include "i915_context.h" #include "i915_state.h" #include "i915_reg.h" -#include "i915_fpc.h" diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c index cbac4175c8..e5c6d87215 100644 --- a/src/gallium/drivers/i915/i915_state_sampler.c +++ b/src/gallium/drivers/i915/i915_state_sampler.c @@ -27,7 +27,6 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" -#include "util/u_memory.h" #include "i915_state_inlines.h" #include "i915_context.h" diff --git a/src/gallium/drivers/i915/i915_surface.c b/src/gallium/drivers/i915/i915_surface.c index c693eb30e8..1ff6b9f4c6 100644 --- a/src/gallium/drivers/i915/i915_surface.c +++ b/src/gallium/drivers/i915/i915_surface.c @@ -27,14 +27,8 @@ #include "i915_context.h" #include "i915_blit.h" -#include "i915_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" -#include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" #include "util/u_format.h" -#include "util/u_tile.h" -#include "util/u_rect.h" /* Assumes all values are within bounds -- no checking at this level - diff --git a/src/gallium/drivers/i915/i915_texture.c b/src/gallium/drivers/i915/i915_texture.c index 50a9e19094..612e5c1cdd 100644 --- a/src/gallium/drivers/i915/i915_texture.c +++ b/src/gallium/drivers/i915/i915_texture.c @@ -34,14 +34,12 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" #include "i915_context.h" #include "i915_texture.h" -#include "i915_debug.h" #include "i915_screen.h" #include "intel_winsys.h" diff --git a/src/gallium/drivers/i965/brw_batchbuffer.c b/src/gallium/drivers/i965/brw_batchbuffer.c index 22607dc608..003b1fd5bf 100644 --- a/src/gallium/drivers/i965/brw_batchbuffer.c +++ b/src/gallium/drivers/i965/brw_batchbuffer.c @@ -155,7 +155,7 @@ _brw_batchbuffer_flush(struct brw_batchbuffer *batch, enum pipe_error brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch, struct brw_winsys_buffer *buffer, - uint32_t usage, + enum brw_buffer_usage usage, uint32_t delta) { int ret; diff --git a/src/gallium/drivers/i965/brw_batchbuffer.h b/src/gallium/drivers/i965/brw_batchbuffer.h index 7473f5bea4..6ca9f617f5 100644 --- a/src/gallium/drivers/i965/brw_batchbuffer.h +++ b/src/gallium/drivers/i965/brw_batchbuffer.h @@ -64,12 +64,12 @@ brw_batchbuffer_reset(struct brw_batchbuffer *batch); * Consider it a convenience function wrapping multple * intel_buffer_dword() calls. */ -int brw_batchbuffer_data(struct brw_batchbuffer *batch, +enum pipe_error brw_batchbuffer_data(struct brw_batchbuffer *batch, const void *data, GLuint bytes, enum cliprect_mode cliprect_mode); -int brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch, +enum pipe_error brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch, struct brw_winsys_buffer *buffer, enum brw_buffer_usage usage, uint32_t offset); diff --git a/src/gallium/drivers/i965/brw_cc.c b/src/gallium/drivers/i965/brw_cc.c index 3e070f5591..4a543276f5 100644 --- a/src/gallium/drivers/i965/brw_cc.c +++ b/src/gallium/drivers/i965/brw_cc.c @@ -32,7 +32,6 @@ #include "brw_context.h" #include "brw_state.h" -#include "brw_defines.h" static enum pipe_error prepare_cc_vp( struct brw_context *brw ) diff --git a/src/gallium/drivers/i965/brw_clip.c b/src/gallium/drivers/i965/brw_clip.c index d67a1a6263..ccba205e8c 100644 --- a/src/gallium/drivers/i965/brw_clip.c +++ b/src/gallium/drivers/i965/brw_clip.c @@ -38,7 +38,6 @@ #include "brw_defines.h" #include "brw_context.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_state.h" #include "brw_pipe_rast.h" #include "brw_clip.h" diff --git a/src/gallium/drivers/i965/brw_clip_line.c b/src/gallium/drivers/i965/brw_clip_line.c index 54282d975e..66caadc4d5 100644 --- a/src/gallium/drivers/i965/brw_clip_line.c +++ b/src/gallium/drivers/i965/brw_clip_line.c @@ -33,7 +33,6 @@ #include "brw_defines.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_clip.h" diff --git a/src/gallium/drivers/i965/brw_clip_point.c b/src/gallium/drivers/i965/brw_clip_point.c index e0a5330556..124156c1b5 100644 --- a/src/gallium/drivers/i965/brw_clip_point.c +++ b/src/gallium/drivers/i965/brw_clip_point.c @@ -31,7 +31,6 @@ #include "brw_defines.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_clip.h" diff --git a/src/gallium/drivers/i965/brw_clip_tri.c b/src/gallium/drivers/i965/brw_clip_tri.c index 4cde7294ea..069524bc14 100644 --- a/src/gallium/drivers/i965/brw_clip_tri.c +++ b/src/gallium/drivers/i965/brw_clip_tri.c @@ -31,7 +31,6 @@ #include "brw_defines.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_clip.h" static void release_tmps( struct brw_clip_compile *c ) diff --git a/src/gallium/drivers/i965/brw_clip_util.c b/src/gallium/drivers/i965/brw_clip_util.c index 97a5710310..23e51ee9bc 100644 --- a/src/gallium/drivers/i965/brw_clip_util.c +++ b/src/gallium/drivers/i965/brw_clip_util.c @@ -32,7 +32,6 @@ #include "brw_defines.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_clip.h" diff --git a/src/gallium/drivers/i965/brw_context.c b/src/gallium/drivers/i965/brw_context.c index e67551882d..d60b7b99b6 100644 --- a/src/gallium/drivers/i965/brw_context.c +++ b/src/gallium/drivers/i965/brw_context.c @@ -34,7 +34,6 @@ #include "util/u_simple_list.h" #include "brw_context.h" -#include "brw_defines.h" #include "brw_draw.h" #include "brw_state.h" #include "brw_batchbuffer.h" diff --git a/src/gallium/drivers/i965/brw_curbe.c b/src/gallium/drivers/i965/brw_curbe.c index 3f031577d5..4b215a001c 100644 --- a/src/gallium/drivers/i965/brw_curbe.c +++ b/src/gallium/drivers/i965/brw_curbe.c @@ -36,9 +36,7 @@ #include "brw_context.h" #include "brw_defines.h" #include "brw_state.h" -#include "brw_util.h" #include "brw_debug.h" -#include "brw_screen.h" /** diff --git a/src/gallium/drivers/i965/brw_draw.c b/src/gallium/drivers/i965/brw_draw.c index ea8d39adaf..1b5cd23995 100644 --- a/src/gallium/drivers/i965/brw_draw.c +++ b/src/gallium/drivers/i965/brw_draw.c @@ -34,7 +34,6 @@ #include "brw_context.h" #include "brw_state.h" #include "brw_debug.h" -#include "brw_screen.h" #include "brw_batchbuffer.h" diff --git a/src/gallium/drivers/i965/brw_gs.c b/src/gallium/drivers/i965/brw_gs.c index 921b201bae..06826635a8 100644 --- a/src/gallium/drivers/i965/brw_gs.c +++ b/src/gallium/drivers/i965/brw_gs.c @@ -34,7 +34,6 @@ #include "brw_defines.h" #include "brw_context.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_state.h" #include "brw_gs.h" diff --git a/src/gallium/drivers/i965/brw_gs_emit.c b/src/gallium/drivers/i965/brw_gs_emit.c index fd8e2acced..9b58773b3b 100644 --- a/src/gallium/drivers/i965/brw_gs_emit.c +++ b/src/gallium/drivers/i965/brw_gs_emit.c @@ -35,7 +35,6 @@ #include "brw_defines.h" #include "brw_context.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_gs.h" static void brw_gs_alloc_regs( struct brw_gs_compile *c, diff --git a/src/gallium/drivers/i965/brw_pipe_blend.c b/src/gallium/drivers/i965/brw_pipe_blend.c index b759a910b6..21f786f871 100644 --- a/src/gallium/drivers/i965/brw_pipe_blend.c +++ b/src/gallium/drivers/i965/brw_pipe_blend.c @@ -118,14 +118,14 @@ static void *brw_create_blend_state( struct pipe_context *pipe, blend->cc2.logicop_enable = 1; blend->cc5.logicop_func = translate_logicop(templ->logicop_func); } - else if (templ->blend_enable) { - blend->cc6.dest_blend_factor = translate_blend_factor(templ->rgb_dst_factor); - blend->cc6.src_blend_factor = translate_blend_factor(templ->rgb_src_factor); - blend->cc6.blend_function = translate_blend_equation(templ->rgb_func); + else if (templ->rt[0].blend_enable) { + blend->cc6.dest_blend_factor = translate_blend_factor(templ->rt[0].rgb_dst_factor); + blend->cc6.src_blend_factor = translate_blend_factor(templ->rt[0].rgb_src_factor); + blend->cc6.blend_function = translate_blend_equation(templ->rt[0].rgb_func); - blend->cc5.ia_dest_blend_factor = translate_blend_factor(templ->alpha_dst_factor); - blend->cc5.ia_src_blend_factor = translate_blend_factor(templ->alpha_src_factor); - blend->cc5.ia_blend_function = translate_blend_equation(templ->alpha_func); + blend->cc5.ia_dest_blend_factor = translate_blend_factor(templ->rt[0].alpha_dst_factor); + blend->cc5.ia_src_blend_factor = translate_blend_factor(templ->rt[0].alpha_src_factor); + blend->cc5.ia_blend_function = translate_blend_equation(templ->rt[0].alpha_func); blend->cc3.blend_enable = 1; blend->cc3.ia_blend_enable = @@ -146,10 +146,10 @@ static void *brw_create_blend_state( struct pipe_context *pipe, /* Per-surface color mask -- just follow global state: */ - blend->ss0.writedisable_red = (templ->colormask & PIPE_MASK_R) ? 0 : 1; - blend->ss0.writedisable_green = (templ->colormask & PIPE_MASK_G) ? 0 : 1; - blend->ss0.writedisable_blue = (templ->colormask & PIPE_MASK_B) ? 0 : 1; - blend->ss0.writedisable_alpha = (templ->colormask & PIPE_MASK_A) ? 0 : 1; + blend->ss0.writedisable_red = (templ->rt[0].colormask & PIPE_MASK_R) ? 0 : 1; + blend->ss0.writedisable_green = (templ->rt[0].colormask & PIPE_MASK_G) ? 0 : 1; + blend->ss0.writedisable_blue = (templ->rt[0].colormask & PIPE_MASK_B) ? 0 : 1; + blend->ss0.writedisable_alpha = (templ->rt[0].colormask & PIPE_MASK_A) ? 0 : 1; return (void *)blend; } diff --git a/src/gallium/drivers/i965/brw_pipe_fb.c b/src/gallium/drivers/i965/brw_pipe_fb.c index 5d4e5025f9..c1f049272a 100644 --- a/src/gallium/drivers/i965/brw_pipe_fb.c +++ b/src/gallium/drivers/i965/brw_pipe_fb.c @@ -3,7 +3,6 @@ #include "pipe/p_state.h" #include "brw_context.h" -#include "brw_debug.h" /** * called from intelDrawBuffer() diff --git a/src/gallium/drivers/i965/brw_pipe_sampler.c b/src/gallium/drivers/i965/brw_pipe_sampler.c index 81712798a5..ef6c1bb315 100644 --- a/src/gallium/drivers/i965/brw_pipe_sampler.c +++ b/src/gallium/drivers/i965/brw_pipe_sampler.c @@ -7,7 +7,6 @@ #include "brw_context.h" #include "brw_defines.h" -#include "brw_debug.h" diff --git a/src/gallium/drivers/i965/brw_screen.c b/src/gallium/drivers/i965/brw_screen.c index 0ecacac9a3..a8f9892d71 100644 --- a/src/gallium/drivers/i965/brw_screen.c +++ b/src/gallium/drivers/i965/brw_screen.c @@ -138,6 +138,9 @@ brw_get_name(struct pipe_screen *screen) case PCI_CHIP_ILM_G: chipset = "ILM_G"; break; + default: + chipset = "unknown"; + break; } util_snprintf(buffer, sizeof(buffer), "i965 (chipset: %s)", chipset); @@ -172,6 +175,12 @@ brw_get_param(struct pipe_screen *screen, int param) return 8; /* max 128x128x128 */ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 11; /* max 1024x1024 */ + 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; default: return 0; } diff --git a/src/gallium/drivers/i965/brw_sf.c b/src/gallium/drivers/i965/brw_sf.c index e1986a9dbb..6e99eaa09d 100644 --- a/src/gallium/drivers/i965/brw_sf.c +++ b/src/gallium/drivers/i965/brw_sf.c @@ -36,7 +36,6 @@ #include "brw_context.h" #include "brw_pipe_rast.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_sf.h" #include "brw_state.h" diff --git a/src/gallium/drivers/i965/brw_sf_emit.c b/src/gallium/drivers/i965/brw_sf_emit.c index 3b85725e36..497634ec9e 100644 --- a/src/gallium/drivers/i965/brw_sf_emit.c +++ b/src/gallium/drivers/i965/brw_sf_emit.c @@ -35,7 +35,6 @@ #include "brw_defines.h" #include "brw_context.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_sf.h" diff --git a/src/gallium/drivers/i965/brw_state_cache.c b/src/gallium/drivers/i965/brw_state_cache.c index 16b643ceb2..85c20076fb 100644 --- a/src/gallium/drivers/i965/brw_state_cache.c +++ b/src/gallium/drivers/i965/brw_state_cache.c @@ -59,7 +59,6 @@ #include "brw_debug.h" #include "brw_state.h" -#include "brw_batchbuffer.h" /* XXX: Fixme - have to include these to get the sizes of the prog_key * structs: diff --git a/src/gallium/drivers/i965/brw_util.c b/src/gallium/drivers/i965/brw_util.c index 458058d668..1fd2e29713 100644 --- a/src/gallium/drivers/i965/brw_util.c +++ b/src/gallium/drivers/i965/brw_util.c @@ -30,8 +30,6 @@ */ -#include "brw_util.h" -#include "brw_defines.h" diff --git a/src/gallium/drivers/i965/brw_vs.c b/src/gallium/drivers/i965/brw_vs.c index e3ea5a3a13..ca8ee79550 100644 --- a/src/gallium/drivers/i965/brw_vs.c +++ b/src/gallium/drivers/i965/brw_vs.c @@ -33,9 +33,7 @@ #include "brw_context.h" #include "brw_vs.h" -#include "brw_util.h" #include "brw_state.h" -#include "brw_pipe_rast.h" diff --git a/src/gallium/drivers/i965/brw_vs_surface_state.c b/src/gallium/drivers/i965/brw_vs_surface_state.c index 177a5170d2..004e3cb4e6 100644 --- a/src/gallium/drivers/i965/brw_vs_surface_state.c +++ b/src/gallium/drivers/i965/brw_vs_surface_state.c @@ -31,7 +31,6 @@ #include "brw_context.h" #include "brw_state.h" -#include "brw_defines.h" #include "brw_winsys.h" /* XXX: disabled true constant buffer functionality diff --git a/src/gallium/drivers/i965/brw_wm_fp.c b/src/gallium/drivers/i965/brw_wm_fp.c index 9c5b527f89..9c67759ad0 100644 --- a/src/gallium/drivers/i965/brw_wm_fp.c +++ b/src/gallium/drivers/i965/brw_wm_fp.c @@ -41,7 +41,6 @@ #include "tgsi/tgsi_util.h" #include "brw_wm.h" -#include "brw_util.h" #include "brw_debug.h" diff --git a/src/gallium/drivers/i965/brw_wm_surface_state.c b/src/gallium/drivers/i965/brw_wm_surface_state.c index f92b8198ed..b01a7f194b 100644 --- a/src/gallium/drivers/i965/brw_wm_surface_state.c +++ b/src/gallium/drivers/i965/brw_wm_surface_state.c @@ -34,7 +34,6 @@ #include "brw_batchbuffer.h" #include "brw_context.h" #include "brw_state.h" -#include "brw_defines.h" #include "brw_screen.h" diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c index 2b4bc5c819..7245730350 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c @@ -35,7 +35,6 @@ #include "lp_bld_type.h" #include "lp_bld_const.h" -#include "lp_bld_arit.h" #include "lp_bld_logic.h" #include "lp_bld_flow.h" #include "lp_bld_debug.h" diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c index ced7b9c11d..ad1dbbc9b1 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c @@ -314,9 +314,10 @@ lp_build_blend_aos(LLVMBuilderRef builder, LLVMValueRef dst_term; /* FIXME */ - assert(blend->colormask == 0xf); + assert(blend->independent_blend_enable == 0); + assert(blend->rt[0].colormask == 0xf); - if(!blend->blend_enable) + if(!blend->rt[0].blend_enable) return src; /* It makes no sense to blend unless values are normalized */ @@ -333,14 +334,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->rgb_src_factor, blend->alpha_src_factor, alpha_swizzle); - dst_term = lp_build_blend_factor(&bld, dst, blend->rgb_dst_factor, blend->alpha_dst_factor, alpha_swizzle); + 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); lp_build_name(src_term, "src_term"); lp_build_name(dst_term, "dst_term"); - if(blend->rgb_func == blend->alpha_func) { - return lp_build_blend_func(&bld.base, blend->rgb_func, src_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); } else { /* Seperate RGB / A functions */ @@ -348,8 +351,8 @@ lp_build_blend_aos(LLVMBuilderRef builder, LLVMValueRef rgb; LLVMValueRef alpha; - rgb = lp_build_blend_func(&bld.base, blend->rgb_func, src_term, dst_term); - alpha = lp_build_blend_func(&bld.base, blend->alpha_func, src_term, dst_term); + 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); 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 9511299d55..a73d1158e7 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c @@ -71,7 +71,6 @@ #include "pipe/p_state.h" #include "lp_bld_type.h" -#include "lp_bld_const.h" #include "lp_bld_arit.h" #include "lp_bld_blend.h" @@ -218,7 +217,7 @@ lp_build_blend_soa(LLVMBuilderRef builder, } for (i = 0; i < 4; ++i) { - if (blend->colormask & (1 << i)) { + if (blend->rt[0].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 +225,10 @@ lp_build_blend_soa(LLVMBuilderRef builder, else res[i] = dst[i]; } - else if (blend->blend_enable) { - unsigned src_factor = i < 3 ? blend->rgb_src_factor : blend->alpha_src_factor; - unsigned dst_factor = i < 3 ? blend->rgb_dst_factor : blend->alpha_dst_factor; - unsigned func = i < 3 ? blend->rgb_func : blend->alpha_func; + 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; boolean func_commutative = lp_build_blend_func_commutative(func); /* It makes no sense to blend unless values are normalized */ @@ -270,7 +269,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->rgb_func : blend->alpha_func; + unsigned prev_func = j < 3 ? blend->rt[0].rgb_func : blend->rt[0].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_conv.c b/src/gallium/drivers/llvmpipe/lp_bld_conv.c index 9fa8837202..f77cf78721 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_conv.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_conv.c @@ -63,11 +63,9 @@ #include "util/u_debug.h" #include "util/u_math.h" -#include "util/u_cpu_detect.h" #include "lp_bld_type.h" #include "lp_bld_const.h" -#include "lp_bld_intr.h" #include "lp_bld_arit.h" #include "lp_bld_pack.h" #include "lp_bld_conv.h" diff --git a/src/gallium/drivers/llvmpipe/lp_bld_format_aos.c b/src/gallium/drivers/llvmpipe/lp_bld_format_aos.c index 10e82f120b..dfa080b853 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_format_aos.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_format_aos.c @@ -38,7 +38,6 @@ #include "lp_bld_type.h" #include "lp_bld_const.h" -#include "lp_bld_logic.h" #include "lp_bld_swizzle.h" #include "lp_bld_format.h" diff --git a/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c index fb1eda4423..85e3b1bdd4 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c @@ -47,13 +47,11 @@ #include "tgsi/tgsi_exec.h" #include "lp_bld_type.h" #include "lp_bld_const.h" -#include "lp_bld_intr.h" #include "lp_bld_arit.h" #include "lp_bld_logic.h" #include "lp_bld_swizzle.h" #include "lp_bld_flow.h" #include "lp_bld_tgsi.h" -#include "lp_bld_debug.h" #define LP_MAX_TEMPS 256 diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c index 3989cce744..3dd68d5794 100644 --- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c +++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c @@ -33,8 +33,6 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" #include "util/u_prim.h" #include "lp_buffer.h" diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c index 07f32848c7..edd480d7ed 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.c +++ b/src/gallium/drivers/llvmpipe/lp_flush.c @@ -35,7 +35,6 @@ #include "lp_flush.h" #include "lp_context.h" #include "lp_surface.h" -#include "lp_winsys.h" #include "lp_setup.h" diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index 9fad7033db..310fc2b847 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -40,7 +40,6 @@ #include "lp_debug.h" #include "lp_screen.h" #include "lp_bld_intr.h" -#include "lp_bld_misc.h" #include "lp_jit.h" diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index a3adc81e9f..ca64c41827 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -115,6 +115,16 @@ llvmpipe_get_param(struct pipe_screen *screen, int param) return 1; case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 0; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 0; default: return 0; } diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index a7514ee011..0602e940d9 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -66,7 +66,6 @@ #include "util/u_format.h" #include "util/u_debug_dump.h" #include "util/u_time.h" -#include "pipe/internal/p_winsys_screen.h" #include "pipe/p_shader_tokens.h" #include "draw/draw_context.h" #include "tgsi/tgsi_dump.h" @@ -568,7 +567,7 @@ generate_blend(const struct pipe_blend_state *blend, lp_build_blend_soa(builder, blend, type, src, dst, con, res); for(chan = 0; chan < 4; ++chan) { - if(blend->colormask & (1 << chan)) { + if(blend->rt[0].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]); @@ -871,15 +870,15 @@ generate_variant(struct llvmpipe_context *lp, if(key->blend.logicop_enable) { debug_printf("blend.logicop_func = %u\n", key->blend.logicop_func); } - else if(key->blend.blend_enable) { - debug_printf("blend.rgb_func = %s\n", debug_dump_blend_func (key->blend.rgb_func, TRUE)); - debug_printf("rgb_src_factor = %s\n", debug_dump_blend_factor(key->blend.rgb_src_factor, TRUE)); - debug_printf("rgb_dst_factor = %s\n", debug_dump_blend_factor(key->blend.rgb_dst_factor, TRUE)); - debug_printf("alpha_func = %s\n", debug_dump_blend_func (key->blend.alpha_func, TRUE)); - debug_printf("alpha_src_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_src_factor, TRUE)); - debug_printf("alpha_dst_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_dst_factor, TRUE)); + else if(key->blend.rt[0].blend_enable) { + debug_printf("blend.rgb_func = %s\n", debug_dump_blend_func (key->blend.rt[0].rgb_func, TRUE)); + debug_printf("rgb_src_factor = %s\n", debug_dump_blend_factor(key->blend.rt[0].rgb_src_factor, TRUE)); + debug_printf("rgb_dst_factor = %s\n", debug_dump_blend_factor(key->blend.rt[0].rgb_dst_factor, TRUE)); + debug_printf("alpha_func = %s\n", debug_dump_blend_func (key->blend.rt[0].alpha_func, TRUE)); + debug_printf("alpha_src_factor = %s\n", debug_dump_blend_factor(key->blend.rt[0].alpha_src_factor, TRUE)); + debug_printf("alpha_dst_factor = %s\n", debug_dump_blend_factor(key->blend.rt[0].alpha_dst_factor, TRUE)); } - debug_printf("blend.colormask = 0x%x\n", key->blend.colormask); + 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); @@ -1020,7 +1019,7 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe, pipe_buffer_reference(&llvmpipe->constants[shader], constants); if(shader == PIPE_SHADER_VERTEX) { - draw_set_mapped_constant_buffer(llvmpipe->draw, PIPE_SHADER_VERTEX, + draw_set_mapped_constant_buffer(llvmpipe->draw, PIPE_SHADER_VERTEX, 0, data, size); } @@ -1078,7 +1077,7 @@ make_variant_key(struct llvmpipe_context *lp, enum util_format_swizzle swizzle = format_desc->swizzle[chan]; if(swizzle <= UTIL_FORMAT_SWIZZLE_W) - key->cbuf_blend[i].colormask |= (1 << chan); + key->blend.rt[0].colormask |= (1 << chan); } } @@ -1128,8 +1127,8 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) /* TODO: put this in the variant */ /* TODO: most of these can be relaxed, in particular the colormask */ opaque = !key.blend.logicop_enable && - !key.blend.blend_enable && - key.blend.colormask == 0xf && + !key.blend.rt[0].blend_enable && + key.blend.rt[0].colormask == 0xf && !key.alpha.enabled && !key.depth.enabled && !key.scissor && diff --git a/src/gallium/drivers/llvmpipe/lp_state_surface.c b/src/gallium/drivers/llvmpipe/lp_state_surface.c index 0e9f03b90b..aa4241a80d 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_state_surface.c @@ -32,7 +32,6 @@ #include "util/u_surface.h" #include "lp_context.h" #include "lp_state.h" -#include "lp_surface.h" #include "lp_setup.h" #include "draw/draw_context.h" diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c index 1a17631a4c..57ac25ea0c 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_vertex.c +++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c @@ -31,7 +31,6 @@ #include "lp_context.h" #include "lp_state.h" -#include "lp_surface.h" #include "draw/draw_context.h" diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c index 6c29e8d8ac..ee72f6ce4f 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_blend.c +++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c @@ -38,7 +38,6 @@ #include "lp_bld_type.h" -#include "lp_bld_arit.h" #include "lp_bld_blend.h" #include "lp_bld_debug.h" #include "lp_test.h" @@ -104,18 +103,18 @@ write_tsv_row(FILE *fp, fprintf(fp, "%s\t%s\t%s\t", - blend->rgb_func != blend->alpha_func ? "true" : "false", - blend->rgb_src_factor != blend->alpha_src_factor ? "true" : "false", - blend->rgb_dst_factor != blend->alpha_dst_factor ? "true" : "false"); + blend->rt[0].rgb_func != blend->rt[0].alpha_func ? "true" : "false", + blend->rt[0].rgb_src_factor != blend->rt[0].alpha_src_factor ? "true" : "false", + blend->rt[0].rgb_dst_factor != blend->rt[0].alpha_dst_factor ? "true" : "false"); fprintf(fp, "%s\t%s\t%s\t%s\t%s\t%s\n", - debug_dump_blend_func(blend->rgb_func, TRUE), - debug_dump_blend_factor(blend->rgb_src_factor, TRUE), - debug_dump_blend_factor(blend->rgb_dst_factor, TRUE), - debug_dump_blend_func(blend->alpha_func, TRUE), - debug_dump_blend_factor(blend->alpha_src_factor, TRUE), - debug_dump_blend_factor(blend->alpha_dst_factor, TRUE)); + debug_dump_blend_func(blend->rt[0].rgb_func, TRUE), + debug_dump_blend_factor(blend->rt[0].rgb_src_factor, TRUE), + debug_dump_blend_factor(blend->rt[0].rgb_dst_factor, TRUE), + debug_dump_blend_func(blend->rt[0].alpha_func, TRUE), + debug_dump_blend_factor(blend->rt[0].alpha_src_factor, TRUE), + debug_dump_blend_factor(blend->rt[0].alpha_dst_factor, TRUE)); fflush(fp); } @@ -137,12 +136,12 @@ dump_blend_type(FILE *fp, fprintf(fp, " %s=%s %s=%s %s=%s %s=%s %s=%s %s=%s", - "rgb_func", debug_dump_blend_func(blend->rgb_func, TRUE), - "rgb_src_factor", debug_dump_blend_factor(blend->rgb_src_factor, TRUE), - "rgb_dst_factor", debug_dump_blend_factor(blend->rgb_dst_factor, TRUE), - "alpha_func", debug_dump_blend_func(blend->alpha_func, TRUE), - "alpha_src_factor", debug_dump_blend_factor(blend->alpha_src_factor, TRUE), - "alpha_dst_factor", debug_dump_blend_factor(blend->alpha_dst_factor, TRUE)); + "rgb_func", debug_dump_blend_func(blend->rt[0].rgb_func, TRUE), + "rgb_src_factor", debug_dump_blend_factor(blend->rt[0].rgb_src_factor, TRUE), + "rgb_dst_factor", debug_dump_blend_factor(blend->rt[0].rgb_dst_factor, TRUE), + "alpha_func", debug_dump_blend_func(blend->rt[0].alpha_func, TRUE), + "alpha_src_factor", debug_dump_blend_factor(blend->rt[0].alpha_src_factor, TRUE), + "alpha_dst_factor", debug_dump_blend_factor(blend->rt[0].alpha_dst_factor, TRUE)); fprintf(fp, " ...\n"); fflush(fp); @@ -401,13 +400,15 @@ compute_blend_ref(const struct pipe_blend_state *blend, double src_term[4]; double dst_term[4]; - compute_blend_ref_term(blend->rgb_src_factor, blend->alpha_src_factor, src, src, dst, con, src_term); - compute_blend_ref_term(blend->rgb_dst_factor, blend->alpha_dst_factor, dst, src, dst, con, dst_term); + compute_blend_ref_term(blend->rt[0].rgb_src_factor, blend->rt[0].alpha_src_factor, + src, src, dst, con, src_term); + compute_blend_ref_term(blend->rt[0].rgb_dst_factor, blend->rt[0].alpha_dst_factor, + dst, src, dst, con, dst_term); /* * Combine RGB terms */ - switch (blend->rgb_func) { + switch (blend->rt[0].rgb_func) { case PIPE_BLEND_ADD: ADD_SAT(res[0], src_term[0], dst_term[0]); /* R */ ADD_SAT(res[1], src_term[1], dst_term[1]); /* G */ @@ -440,7 +441,7 @@ compute_blend_ref(const struct pipe_blend_state *blend, /* * Combine A terms */ - switch (blend->alpha_func) { + switch (blend->rt[0].alpha_func) { case PIPE_BLEND_ADD: ADD_SAT(res[3], src_term[3], dst_term[3]); /* A */ break; @@ -806,14 +807,14 @@ test_all(unsigned verbose, FILE *fp) continue; memset(&blend, 0, sizeof blend); - blend.blend_enable = 1; - blend.rgb_func = *rgb_func; - blend.rgb_src_factor = *rgb_src_factor; - blend.rgb_dst_factor = *rgb_dst_factor; - blend.alpha_func = *alpha_func; - blend.alpha_src_factor = *alpha_src_factor; - blend.alpha_dst_factor = *alpha_dst_factor; - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].blend_enable = 1; + blend.rt[0].rgb_func = *rgb_func; + blend.rt[0].rgb_src_factor = *rgb_src_factor; + blend.rt[0].rgb_dst_factor = *rgb_dst_factor; + blend.rt[0].alpha_func = *alpha_func; + blend.rt[0].alpha_src_factor = *alpha_src_factor; + blend.rt[0].alpha_dst_factor = *alpha_dst_factor; + blend.rt[0].colormask = PIPE_MASK_RGBA; if(!test_one(verbose, fp, &blend, mode, *type)) success = FALSE; @@ -865,14 +866,14 @@ test_some(unsigned verbose, FILE *fp, unsigned long n) type = &blend_types[rand() % num_types]; memset(&blend, 0, sizeof blend); - blend.blend_enable = 1; - blend.rgb_func = *rgb_func; - blend.rgb_src_factor = *rgb_src_factor; - blend.rgb_dst_factor = *rgb_dst_factor; - blend.alpha_func = *alpha_func; - blend.alpha_src_factor = *alpha_src_factor; - blend.alpha_dst_factor = *alpha_dst_factor; - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].blend_enable = 1; + blend.rt[0].rgb_func = *rgb_func; + blend.rt[0].rgb_src_factor = *rgb_src_factor; + blend.rt[0].rgb_dst_factor = *rgb_dst_factor; + blend.rt[0].alpha_func = *alpha_func; + blend.rt[0].alpha_src_factor = *alpha_src_factor; + blend.rt[0].alpha_dst_factor = *alpha_dst_factor; + blend.rt[0].colormask = PIPE_MASK_RGBA; if(!test_one(verbose, fp, &blend, mode, *type)) success = FALSE; diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c index d59d768139..7f55f1ae83 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c @@ -44,7 +44,6 @@ #include "pipe/p_shader_tokens.h" #include "lp_bld_debug.h" #include "lp_bld_type.h" -#include "lp_bld_intr.h" #include "lp_bld_sample.h" #include "lp_bld_tgsi.h" #include "lp_jit.h" diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 36e2ebb41a..c9b6eb180f 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -33,7 +33,6 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" #include "util/u_format.h" #include "util/u_math.h" diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c index 7ebc94ed6c..1ad539d285 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.c +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -260,6 +260,8 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) void nouveau_screen_fini(struct nouveau_screen *screen) { + struct pipe_winsys *ws = screen->base.winsys; nouveau_channel_free(&screen->channel); + ws->destroy(ws); } diff --git a/src/gallium/drivers/nv04/nv04_screen.c b/src/gallium/drivers/nv04/nv04_screen.c index 7c5b6e8229..97538964af 100644 --- a/src/gallium/drivers/nv04/nv04_screen.c +++ b/src/gallium/drivers/nv04/nv04_screen.c @@ -45,6 +45,16 @@ nv04_screen_get_param(struct pipe_screen *screen, int param) case NOUVEAU_CAP_HW_VTXBUF: case NOUVEAU_CAP_HW_IDXBUF: return 0; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 0; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; diff --git a/src/gallium/drivers/nv04/nv04_state.c b/src/gallium/drivers/nv04/nv04_state.c index b67f1e16b1..1fdb764b53 100644 --- a/src/gallium/drivers/nv04/nv04_state.c +++ b/src/gallium/drivers/nv04/nv04_state.c @@ -17,11 +17,11 @@ nv04_blend_state_create(struct pipe_context *pipe, cb = MALLOC(sizeof(struct nv04_blend_state)); - cb->b_enable = cso->blend_enable ? 1 : 0; - cb->b_src = ((nvgl_blend_func(cso->alpha_src_factor)<<16) | - (nvgl_blend_func(cso->rgb_src_factor))); - cb->b_dst = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) | - (nvgl_blend_func(cso->rgb_dst_factor))); + cb->b_enable = cso->rt[0].blend_enable ? 1 : 0; + cb->b_src = ((nvgl_blend_func(cso->rt[0].alpha_src_factor)<<16) | + (nvgl_blend_func(cso->rt[0].rgb_src_factor))); + cb->b_dst = ((nvgl_blend_func(cso->rt[0].alpha_dst_factor)<<16) | + (nvgl_blend_func(cso->rt[0].rgb_dst_factor))); return (void *)cb; diff --git a/src/gallium/drivers/nv04/nv04_vbo.c b/src/gallium/drivers/nv04/nv04_vbo.c index 3484771814..2db61d8941 100644 --- a/src/gallium/drivers/nv04/nv04_vbo.c +++ b/src/gallium/drivers/nv04/nv04_vbo.c @@ -45,7 +45,7 @@ void nv04_draw_elements( struct pipe_context *pipe, draw_set_mapped_element_buffer(draw, 0, NULL); } - draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, + draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, nv04->constbuf[PIPE_SHADER_VERTEX], nv04->constbuf_nr[PIPE_SHADER_VERTEX]); diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c index 69a6dab866..4e6bc12994 100644 --- a/src/gallium/drivers/nv10/nv10_screen.c +++ b/src/gallium/drivers/nv10/nv10_screen.c @@ -40,6 +40,16 @@ nv10_screen_get_param(struct pipe_screen *screen, int param) case NOUVEAU_CAP_HW_VTXBUF: case NOUVEAU_CAP_HW_IDXBUF: return 0; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 0; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; diff --git a/src/gallium/drivers/nv10/nv10_state.c b/src/gallium/drivers/nv10/nv10_state.c index ad7def53b1..9aafc60411 100644 --- a/src/gallium/drivers/nv10/nv10_state.c +++ b/src/gallium/drivers/nv10/nv10_state.c @@ -17,16 +17,16 @@ nv10_blend_state_create(struct pipe_context *pipe, cb = MALLOC(sizeof(struct nv10_blend_state)); - cb->b_enable = cso->blend_enable ? 1 : 0; - cb->b_srcfunc = ((nvgl_blend_func(cso->alpha_src_factor)<<16) | - (nvgl_blend_func(cso->rgb_src_factor))); - cb->b_dstfunc = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) | - (nvgl_blend_func(cso->rgb_dst_factor))); - - cb->c_mask = (((cso->colormask & PIPE_MASK_A) ? (0x01<<24) : 0) | - ((cso->colormask & PIPE_MASK_R) ? (0x01<<16) : 0) | - ((cso->colormask & PIPE_MASK_G) ? (0x01<< 8) : 0) | - ((cso->colormask & PIPE_MASK_B) ? (0x01<< 0) : 0)); + cb->b_enable = cso->rt[0].blend_enable ? 1 : 0; + cb->b_srcfunc = ((nvgl_blend_func(cso->rt[0].alpha_src_factor)<<16) | + (nvgl_blend_func(cso->rt[0].rgb_src_factor))); + cb->b_dstfunc = ((nvgl_blend_func(cso->rt[0].alpha_dst_factor)<<16) | + (nvgl_blend_func(cso->rt[0].rgb_dst_factor))); + + cb->c_mask = (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01<<24) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01<<16) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01<< 8) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01<< 0) : 0)); cb->d_enable = cso->dither ? 1 : 0; diff --git a/src/gallium/drivers/nv10/nv10_vbo.c b/src/gallium/drivers/nv10/nv10_vbo.c index 9180c72c9b..da5c93f081 100644 --- a/src/gallium/drivers/nv10/nv10_vbo.c +++ b/src/gallium/drivers/nv10/nv10_vbo.c @@ -46,6 +46,7 @@ void nv10_draw_elements( struct pipe_context *pipe, draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, + 0, nv10->constbuf[PIPE_SHADER_VERTEX], nv10->constbuf_nr[PIPE_SHADER_VERTEX]); diff --git a/src/gallium/drivers/nv20/nv20_screen.c b/src/gallium/drivers/nv20/nv20_screen.c index d091335063..df9401bcce 100644 --- a/src/gallium/drivers/nv20/nv20_screen.c +++ b/src/gallium/drivers/nv20/nv20_screen.c @@ -40,6 +40,16 @@ nv20_screen_get_param(struct pipe_screen *screen, int param) case NOUVEAU_CAP_HW_VTXBUF: case NOUVEAU_CAP_HW_IDXBUF: return 0; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 0; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; diff --git a/src/gallium/drivers/nv20/nv20_state.c b/src/gallium/drivers/nv20/nv20_state.c index 45697a60ef..83335c790a 100644 --- a/src/gallium/drivers/nv20/nv20_state.c +++ b/src/gallium/drivers/nv20/nv20_state.c @@ -17,16 +17,16 @@ nv20_blend_state_create(struct pipe_context *pipe, cb = MALLOC(sizeof(struct nv20_blend_state)); - cb->b_enable = cso->blend_enable ? 1 : 0; - cb->b_srcfunc = ((nvgl_blend_func(cso->alpha_src_factor)<<16) | - (nvgl_blend_func(cso->rgb_src_factor))); - cb->b_dstfunc = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) | - (nvgl_blend_func(cso->rgb_dst_factor))); - - cb->c_mask = (((cso->colormask & PIPE_MASK_A) ? (0x01<<24) : 0) | - ((cso->colormask & PIPE_MASK_R) ? (0x01<<16) : 0) | - ((cso->colormask & PIPE_MASK_G) ? (0x01<< 8) : 0) | - ((cso->colormask & PIPE_MASK_B) ? (0x01<< 0) : 0)); + cb->b_enable = cso->rt[0].blend_enable ? 1 : 0; + cb->b_srcfunc = ((nvgl_blend_func(cso->rt[0].alpha_src_factor)<<16) | + (nvgl_blend_func(cso->rt[0].rgb_src_factor))); + cb->b_dstfunc = ((nvgl_blend_func(cso->rt[0].alpha_dst_factor)<<16) | + (nvgl_blend_func(cso->rt[0].rgb_dst_factor))); + + cb->c_mask = (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01<<24) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01<<16) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01<< 8) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01<< 0) : 0)); cb->d_enable = cso->dither ? 1 : 0; diff --git a/src/gallium/drivers/nv20/nv20_vbo.c b/src/gallium/drivers/nv20/nv20_vbo.c index 52991a0d85..6dc9538901 100644 --- a/src/gallium/drivers/nv20/nv20_vbo.c +++ b/src/gallium/drivers/nv20/nv20_vbo.c @@ -45,7 +45,7 @@ void nv20_draw_elements( struct pipe_context *pipe, draw_set_mapped_element_buffer(draw, 0, NULL); } - draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, + draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, nv20->constbuf[PIPE_SHADER_VERTEX], nv20->constbuf_nr[PIPE_SHADER_VERTEX]); diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index 9ed48178dc..ee83ec5676 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -67,6 +67,16 @@ nv30_screen_get_param(struct pipe_screen *pscreen, int param) case NOUVEAU_CAP_HW_VTXBUF: case NOUVEAU_CAP_HW_IDXBUF: return 1; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 0; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c index 065c927a10..1f4c964270 100644 --- a/src/gallium/drivers/nv30/nv30_state.c +++ b/src/gallium/drivers/nv30/nv30_state.c @@ -16,27 +16,27 @@ nv30_blend_state_create(struct pipe_context *pipe, struct nv30_blend_state *bso = CALLOC(1, sizeof(*bso)); struct nouveau_stateobj *so = so_new(5, 8, 0); - if (cso->blend_enable) { + if (cso->rt[0].blend_enable) { so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 3); so_data (so, 1); - so_data (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) | - nvgl_blend_func(cso->rgb_src_factor)); - so_data (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 | - nvgl_blend_func(cso->rgb_dst_factor)); + so_data (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | + nvgl_blend_func(cso->rt[0].rgb_src_factor)); + so_data (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 | + nvgl_blend_func(cso->rt[0].rgb_dst_factor)); /* FIXME: Gallium assumes GL_EXT_blend_func_separate. It is not the case for NV30 */ so_method(so, rankine, NV34TCL_BLEND_EQUATION, 1); - so_data (so, nvgl_blend_eqn(cso->rgb_func)); + so_data (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); } else { so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 1); so_data (so, 0); } so_method(so, rankine, NV34TCL_COLOR_MASK, 1); - so_data (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | - ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | - ((cso->colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | - ((cso->colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); + so_data (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); if (cso->logicop_enable) { so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2); diff --git a/src/gallium/drivers/nv40/nv40_draw.c b/src/gallium/drivers/nv40/nv40_draw.c index d826f8c2f5..a2fd5f6c02 100644 --- a/src/gallium/drivers/nv40/nv40_draw.c +++ b/src/gallium/drivers/nv40/nv40_draw.c @@ -271,7 +271,7 @@ nv40_draw_elements_swtnl(struct pipe_context *pipe, map = pipe_buffer_map(pscreen, nv40->constbuf[PIPE_SHADER_VERTEX], PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_constant_buffer(nv40->draw, PIPE_SHADER_VERTEX, + draw_set_mapped_constant_buffer(nv40->draw, PIPE_SHADER_VERTEX, 0, map, nr); } diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index 9e55e5a089..b1a7343b40 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -52,6 +52,16 @@ nv40_screen_get_param(struct pipe_screen *pscreen, int param) if (screen->curie->grclass == NV40TCL) return 1; return 0; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 0; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c index 7d990f7d56..7a63fba18c 100644 --- a/src/gallium/drivers/nv40/nv40_state.c +++ b/src/gallium/drivers/nv40/nv40_state.c @@ -18,26 +18,26 @@ nv40_blend_state_create(struct pipe_context *pipe, struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso)); struct nouveau_stateobj *so = so_new(5, 8, 0); - if (cso->blend_enable) { + if (cso->rt[0].blend_enable) { so_method(so, curie, NV40TCL_BLEND_ENABLE, 3); so_data (so, 1); - so_data (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) | - nvgl_blend_func(cso->rgb_src_factor)); - so_data (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 | - nvgl_blend_func(cso->rgb_dst_factor)); + so_data (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | + nvgl_blend_func(cso->rt[0].rgb_src_factor)); + so_data (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 | + nvgl_blend_func(cso->rt[0].rgb_dst_factor)); so_method(so, curie, NV40TCL_BLEND_EQUATION, 1); - so_data (so, nvgl_blend_eqn(cso->alpha_func) << 16 | - nvgl_blend_eqn(cso->rgb_func)); + so_data (so, nvgl_blend_eqn(cso->rt[0].alpha_func) << 16 | + nvgl_blend_eqn(cso->rt[0].rgb_func)); } else { so_method(so, curie, NV40TCL_BLEND_ENABLE, 1); so_data (so, 0); } so_method(so, curie, NV40TCL_COLOR_MASK, 1); - so_data (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | - ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | - ((cso->colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | - ((cso->colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); + so_data (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); if (cso->logicop_enable) { so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2); diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 22a8498c69..5c705ccc8f 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -34,6 +34,11 @@ nv50_flush(struct pipe_context *pipe, unsigned flags, struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->base.channel; + if (flags & PIPE_FLUSH_TEXTURE_CACHE) { + BEGIN_RING(chan, nv50->screen->tesla, 0x1338, 1); + OUT_RING (chan, 0x20); + } + if (flags & PIPE_FLUSH_FRAME) FIRE_RING(chan); } @@ -81,6 +86,10 @@ nv50_destroy(struct pipe_context *pipe) so_ref(NULL, &nv50->state.vtxattr); draw_destroy(nv50->draw); + + if (nv50->screen->cur_ctx == nv50) + nv50->screen->cur_ctx = NULL; + FREE(nv50); } @@ -104,7 +113,9 @@ nv50_create(struct pipe_screen *pscreen, unsigned pctx_id) nv50->pipe.destroy = nv50_destroy; nv50->pipe.draw_arrays = nv50_draw_arrays; + nv50->pipe.draw_arrays_instanced = nv50_draw_arrays_instanced; nv50->pipe.draw_elements = nv50_draw_elements; + nv50->pipe.draw_elements_instanced = nv50_draw_elements_instanced; nv50->pipe.clear = nv50_clear; nv50->pipe.flush = nv50_flush; diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index d024be6ea9..bebcd95054 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -29,9 +29,7 @@ #define NV50_CB_PVP 1 #define NV50_CB_PFP 2 #define NV50_CB_PGP 3 -#define NV50_CB_TIC 4 -#define NV50_CB_TSC 5 -#define NV50_CB_PUPLOAD 6 +#define NV50_CB_AUX 4 #define NV50_NEW_BLEND (1 << 0) #define NV50_NEW_ZSA (1 << 1) @@ -137,6 +135,7 @@ struct nv50_state { struct nouveau_stateobj *vtxfmt; struct nouveau_stateobj *vtxbuf; struct nouveau_stateobj *vtxattr; + struct nouveau_stateobj *instbuf; unsigned vtxelt_nr; }; @@ -198,11 +197,22 @@ extern struct draw_stage *nv50_draw_render_stage(struct nv50_context *nv50); /* nv50_vbo.c */ extern void nv50_draw_arrays(struct pipe_context *, unsigned mode, unsigned start, unsigned count); +extern void nv50_draw_arrays_instanced(struct pipe_context *, unsigned mode, + unsigned start, unsigned count, + unsigned startInstance, + unsigned instanceCount); extern void nv50_draw_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count); +extern void nv50_draw_elements_instanced(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, + unsigned count, + unsigned startInstance, + unsigned instanceCount); extern void nv50_vbo_validate(struct nv50_context *nv50); /* nv50_clear.c */ diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index acd695b39b..e74a526c62 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -95,6 +95,8 @@ struct nv50_reg { int vtx; /* vertex index, for GP inputs (TGSI Dimension.Index) */ int indirect[2]; /* index into pc->addr, or -1 */ + + ubyte buf_index; /* c{0 .. 15}[] or g{0 .. 15}[] */ }; #define NV50_MOD_NEG 1 @@ -188,6 +190,7 @@ ctor_reg(struct nv50_reg *reg, unsigned type, int index, int hw) reg->vtx = -1; reg->acc = 0; reg->indirect[0] = reg->indirect[1] = -1; + reg->buf_index = (type == P_CONST) ? 1 : 0; } static INLINE unsigned @@ -474,6 +477,12 @@ is_join(struct nv50_program_exec *e) return FALSE; } +static INLINE boolean +is_control_flow(struct nv50_program_exec *e) +{ + return (e->inst[0] & 2); +} + static INLINE void set_pred(struct nv50_pc *pc, unsigned pred, unsigned idx, struct nv50_program_exec *e) @@ -631,7 +640,7 @@ set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s, set_addr(e, pc->addr[src->indirect[0]]); } - e->inst[1] |= (((src->type == P_IMMD) ? 0 : 1) << 22); + e->inst[1] |= (src->buf_index << 22); } /* Never apply nv50_reg::mod in emit_mov, or carefully check the code !!! */ @@ -3163,7 +3172,9 @@ nv50_program_tx_insn(struct nv50_pc *pc, if (!is_long(pc->p->exec_tail)) convert_to_long(pc, pc->p->exec_tail); else - if (is_immd(pc->p->exec_tail) || is_join(pc->p->exec_tail)) + if (is_immd(pc->p->exec_tail) || + is_join(pc->p->exec_tail) || + is_control_flow(pc->p->exec_tail)) emit_nop(pc); pc->p->exec_tail->inst[1] |= 1; /* set exit bit */ @@ -3272,7 +3283,7 @@ prep_inspect_insn(struct nv50_pc *pc, const struct tgsi_full_instruction *insn) static unsigned nv50_revdep_reorder(unsigned m[4], unsigned rdep[4]) { - unsigned i, c, x, unsafe; + unsigned i, c, x, unsafe = 0; for (c = 0; c < 4; c++) m[c] = c; @@ -3483,6 +3494,19 @@ load_frontfacing(struct nv50_pc *pc, struct nv50_reg *sv) } static void +load_instance_id(struct nv50_pc *pc, unsigned index) +{ + struct nv50_reg reg, mem; + + ctor_reg(®, P_TEMP, -1, -1); + ctor_reg(&mem, P_CONST, -1, 24); /* startInstance */ + mem.buf_index = 2; + + emit_add_b32(pc, ®, &pc->sysval[index], &mem); + pc->sysval[index] = reg; +} + +static void copy_semantic_info(struct nv50_program *p) { unsigned i, id; @@ -3668,8 +3692,10 @@ nv50_program_tx_prep(struct nv50_pc *pc) } if (p->cfg.regs[0] & (1 << 0)) pc->sysval[vertex_id].hw = rid++; - if (p->cfg.regs[0] & (1 << 4)) + if (p->cfg.regs[0] & (1 << 4)) { pc->sysval[instance_id].hw = rid++; + load_instance_id(pc, instance_id); + } } for (i = 0, rid = 0; i < pc->result_nr; ++i) { @@ -3702,13 +3728,21 @@ nv50_program_tx_prep(struct nv50_pc *pc) copy_semantic_info(p); } else if (p->type == PIPE_SHADER_FRAGMENT) { - int rid, aid, base; + int rid, aid; unsigned n = 0, m = pc->attr_nr - flat_nr; pc->allow32 = TRUE; - base = (TGSI_SEMANTIC_POSITION == - p->info.input_semantic_name[0]) ? 0 : 1; + /* do we read FragCoord ? */ + if (pc->attr_nr && + p->info.input_semantic_name[0] == TGSI_SEMANTIC_POSITION) { + /* select FCRD components we want accessible */ + for (c = 0; c < 4; ++c) + if (pc->attr[c].acc) + p->cfg.regs[1] |= 1 << (24 + c); + aid = 0; + } else /* offset by 1 if FCRD.w is needed for pinterp */ + aid = popcnt4(p->cfg.regs[1] >> 24); /* non-flat interpolants have to be mapped to * the lower hardware IDs, so sort them: @@ -3724,12 +3758,6 @@ nv50_program_tx_prep(struct nv50_pc *pc) } copy_semantic_info(p); - if (!base) /* set w-coordinate mask from perspective interp */ - p->cfg.in[0].mask |= p->cfg.regs[1] >> 24; - - aid = popcnt4( /* if fcrd isn't contained in cfg.io */ - base ? (p->cfg.regs[1] >> 24) : p->cfg.in[0].mask); - for (n = 0; n < pc->attr_nr; ++n) { p->cfg.in[n].hw = rid = aid; i = p->cfg.in[n].id; @@ -3751,9 +3779,6 @@ nv50_program_tx_prep(struct nv50_pc *pc) aid += popcnt4(p->cfg.in[n].mask); } - if (!base) - p->cfg.regs[1] |= p->cfg.in[0].mask << 24; - m = popcnt4(p->cfg.regs[1] >> 24); /* set count of non-position inputs and of non-flat @@ -4641,6 +4666,7 @@ nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p) nouveau_bo_ref(NULL, &p->bo); + FREE(p->immd); nouveau_resource_free(&p->data[0]); p->translated = 0; diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index 5a4ab3508b..9eba4c9611 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -48,7 +48,7 @@ nv50_query_create(struct pipe_context *pipe, unsigned type) assert (q->type == PIPE_QUERY_OCCLUSION_COUNTER); q->type = type; - ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 256, + ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 256, 16, &q->bo); if (ret) { FREE(q); @@ -95,11 +95,13 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq) MARK_RING (chan, 5, 2); /* flush on lack of space or relocs */ BEGIN_RING(chan, tesla, NV50TCL_QUERY_ADDRESS_HIGH, 4); - OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR); + OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR); OUT_RING (chan, 0x00000000); OUT_RING (chan, 0x0100f002); - FIRE_RING (chan); + + BEGIN_RING(chan, tesla, NV50TCL_SAMPLECNT_ENABLE, 1); + OUT_RING (chan, 0); } static boolean @@ -123,6 +125,35 @@ nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq, return q->ready; } +static void +nv50_render_condition(struct pipe_context *pipe, + struct pipe_query *pq, uint mode) +{ + struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_channel *chan = nv50->screen->base.channel; + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nv50_query *q; + + if (!pq) { + BEGIN_RING(chan, tesla, NV50TCL_COND_MODE, 1); + OUT_RING (chan, NV50TCL_COND_MODE_ALWAYS); + return; + } + q = nv50_query(pq); + + if (mode == PIPE_RENDER_COND_WAIT || + mode == PIPE_RENDER_COND_BY_REGION_WAIT) { + /* XXX: big fence, FIFO semaphore might be better */ + BEGIN_RING(chan, tesla, 0x0110, 1); + OUT_RING (chan, 0); + } + + BEGIN_RING(chan, tesla, NV50TCL_COND_ADDRESS_HIGH, 3); + OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + OUT_RING (chan, NV50TCL_COND_MODE_RES); +} + void nv50_init_query_functions(struct nv50_context *nv50) { @@ -131,4 +162,5 @@ nv50_init_query_functions(struct nv50_context *nv50) nv50->pipe.begin_query = nv50_query_begin; nv50->pipe.end_query = nv50_query_end; nv50->pipe.get_query_result = nv50_query_result; + nv50->pipe.render_condition = nv50_render_condition; } diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 73205652cc..c4465a228c 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -135,6 +135,16 @@ nv50_screen_get_param(struct pipe_screen *pscreen, int param) return 1; case NOUVEAU_CAP_HW_IDXBUF: return 0; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 1; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + 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; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; @@ -329,7 +339,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_ref(NULL, &so); /* Static tesla init */ - so = so_new(44, 90, 22); + so = so_new(47, 95, 24); so_method(so, screen->tesla, NV50TCL_COND_MODE, 1); so_data (so, NV50TCL_COND_MODE_ALWAYS); @@ -372,7 +382,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) } for (i = 0; i < 3; i++) { - ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (128 * 4) * 4, + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (256 * 4) * 4, &screen->constbuf_parm[i]); if (ret) { nv50_screen_destroy(pscreen); @@ -411,6 +421,18 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); so_data (so, 0x00000031 | (NV50_CB_PMISC << 12)); + /* bind auxiliary constbuf to immediate data bo */ + so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); + so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); + so_data (so, (NV50_CB_AUX << 16) | 0x00000200); + so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); + so_data (so, 0x00000201 | (NV50_CB_AUX << 12)); + so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); + so_data (so, 0x00000221 | (NV50_CB_AUX << 12)); + so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 7a155ca9c4..0d786b0f2e 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -23,6 +23,8 @@ struct nv50_screen { struct nouveau_resource *immd_heap[1]; struct nouveau_resource *parm_heap[PIPE_SHADER_TYPES]; + struct pipe_buffer *strm_vbuf[16]; + struct nouveau_bo *tic; struct nouveau_bo *tsc; diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index 6ab33be663..da8dc933b0 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -31,6 +31,23 @@ #include "nouveau/nouveau_stateobj.h" +static INLINE uint32_t +nv50_colormask(unsigned mask) +{ + uint32_t cmask = 0; + + if (mask & PIPE_MASK_R) + cmask |= 0x0001; + if (mask & PIPE_MASK_G) + cmask |= 0x0010; + if (mask & PIPE_MASK_B) + cmask |= 0x0100; + if (mask & PIPE_MASK_A) + cmask |= 0x1000; + + return cmask; +} + static void * nv50_blend_state_create(struct pipe_context *pipe, const struct pipe_blend_state *cso) @@ -38,28 +55,37 @@ nv50_blend_state_create(struct pipe_context *pipe, struct nouveau_stateobj *so = so_new(5, 24, 0); struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla; struct nv50_blend_stateobj *bso = CALLOC_STRUCT(nv50_blend_stateobj); - unsigned cmask = 0, i; + unsigned i, blend_enabled = 0; /*XXX ignored: * - dither */ - if (cso->blend_enable == 0) { - so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8); + so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8); + if (cso->independent_blend_enable) { + for (i = 0; i < 8; ++i) { + so_data(so, cso->rt[i].blend_enable); + if (cso->rt[i].blend_enable) + blend_enabled = 1; + } + } else + if (cso->rt[0].blend_enable) { + blend_enabled = 1; for (i = 0; i < 8; i++) - so_data(so, 0); + so_data(so, 1); } else { - so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8); for (i = 0; i < 8; i++) - so_data(so, 1); + so_data(so, 0); + } + if (blend_enabled) { so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5); - so_data (so, nvgl_blend_eqn(cso->rgb_func)); - so_data (so, 0x4000 | nvgl_blend_func(cso->rgb_src_factor)); - so_data (so, 0x4000 | nvgl_blend_func(cso->rgb_dst_factor)); - so_data (so, nvgl_blend_eqn(cso->alpha_func)); - so_data (so, 0x4000 | nvgl_blend_func(cso->alpha_src_factor)); + so_data (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); + so_data (so, 0x4000 | nvgl_blend_func(cso->rt[0].rgb_src_factor)); + so_data (so, 0x4000 | nvgl_blend_func(cso->rt[0].rgb_dst_factor)); + so_data (so, nvgl_blend_eqn(cso->rt[0].alpha_func)); + so_data (so, 0x4000 | nvgl_blend_func(cso->rt[0].alpha_src_factor)); so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1); - so_data (so, 0x4000 | nvgl_blend_func(cso->alpha_dst_factor)); + so_data (so, 0x4000 | nvgl_blend_func(cso->rt[0].alpha_dst_factor)); } if (cso->logicop_enable == 0 ) { @@ -71,17 +97,15 @@ nv50_blend_state_create(struct pipe_context *pipe, so_data (so, nvgl_logicop_func(cso->logicop_func)); } - if (cso->colormask & PIPE_MASK_R) - cmask |= (1 << 0); - if (cso->colormask & PIPE_MASK_G) - cmask |= (1 << 4); - if (cso->colormask & PIPE_MASK_B) - cmask |= (1 << 8); - if (cso->colormask & PIPE_MASK_A) - cmask |= (1 << 12); so_method(so, tesla, NV50TCL_COLOR_MASK(0), 8); - for (i = 0; i < 8; i++) - so_data(so, cmask); + if (cso->independent_blend_enable) + for (i = 0; i < 8; ++i) + so_data(so, nv50_colormask(cso->rt[i].colormask)); + else { + uint32_t cmask = nv50_colormask(cso->rt[0].colormask); + for (i = 0; i < 8; i++) + so_data(so, cmask); + } bso->pipe = *cso; so_ref(so, &bso->so); diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index fcd07b59cd..956da9b304 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -274,6 +274,9 @@ nv50_state_flush_notify(struct nouveau_channel *chan) so_emit_reloc_markers(chan, nv50->state.fragprog); so_emit_reloc_markers(chan, nv50->state.vtxbuf); so_emit_reloc_markers(chan, nv50->screen->static_init); + + if (nv50->state.instbuf) + so_emit_reloc_markers(chan, nv50->state.instbuf); } boolean diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index 871536dca9..9f1a171303 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -220,11 +220,8 @@ nv50_tex_validate(struct nv50_context *nv50) return; } - /* not sure if the following really do what I think: */ so_method(so, tesla, 0x1330, 1); /* flush TIC */ so_data (so, 0); - so_method(so, tesla, 0x1338, 1); /* flush texture caches */ - so_data (so, 0x20); so_ref(so, &nv50->state.tic_upload); so_ref(NULL, &so); diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index 89a94d2fe8..bfb1b34d27 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -40,6 +40,8 @@ nv50_push_elements_u32(struct nv50_context *, uint32_t *, unsigned); static boolean nv50_push_arrays(struct nv50_context *, unsigned, unsigned); +#define NV50_USING_LOATHED_EDGEFLAG(ctx) ((ctx)->vertprog->cfg.edgeflag_in < 16) + static INLINE unsigned nv50_prim(unsigned mode) { @@ -160,6 +162,309 @@ nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element *ve) return (hw_type | hw_size); } +/* For instanced drawing from user buffers, hitting the FIFO repeatedly + * with the same vertex data is probably worse than uploading all data. + */ +static boolean +nv50_upload_vtxbuf(struct nv50_context *nv50, unsigned i) +{ + struct nv50_screen *nscreen = nv50->screen; + struct pipe_screen *pscreen = &nscreen->base.base; + struct pipe_buffer *buf = nscreen->strm_vbuf[i]; + struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i]; + uint8_t *src; + unsigned size = align(vb->buffer->size, 4096); + + if (buf && buf->size < size) + pipe_buffer_reference(&nscreen->strm_vbuf[i], NULL); + + if (!nscreen->strm_vbuf[i]) { + nscreen->strm_vbuf[i] = pipe_buffer_create( + pscreen, 0, PIPE_BUFFER_USAGE_VERTEX, size); + buf = nscreen->strm_vbuf[i]; + } + + src = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); + if (!src) + return FALSE; + src += vb->buffer_offset; + + size = (vb->max_index + 1) * vb->stride + 16; /* + 16 is for stride 0 */ + if (vb->buffer_offset + size > vb->buffer->size) + size = vb->buffer->size - vb->buffer_offset; + + pipe_buffer_write(pscreen, buf, vb->buffer_offset, size, src); + pipe_buffer_unmap(pscreen, vb->buffer); + + vb->buffer = buf; /* don't pipe_reference, this is a private copy */ + return TRUE; +} + +static void +nv50_upload_user_vbufs(struct nv50_context *nv50) +{ + unsigned i; + + if (nv50->vbo_fifo) + nv50->dirty |= NV50_NEW_ARRAYS; + if (!(nv50->dirty & NV50_NEW_ARRAYS)) + return; + + for (i = 0; i < nv50->vtxbuf_nr; ++i) { + if (nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX) + continue; + nv50_upload_vtxbuf(nv50, i); + } +} + +static void +nv50_set_static_vtxattr(struct nv50_context *nv50, unsigned i, void *data) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + float v[4]; + + util_format_read_4f(nv50->vtxelt[i].src_format, + v, 0, data, 0, 0, 0, 1, 1); + + switch (nv50->vtxelt[i].nr_components) { + case 4: + BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_4F_X(i), 4); + OUT_RINGf (chan, v[0]); + OUT_RINGf (chan, v[1]); + OUT_RINGf (chan, v[2]); + OUT_RINGf (chan, v[3]); + break; + case 3: + BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_3F_X(i), 3); + OUT_RINGf (chan, v[0]); + OUT_RINGf (chan, v[1]); + OUT_RINGf (chan, v[2]); + break; + case 2: + BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_2F_X(i), 2); + OUT_RINGf (chan, v[0]); + OUT_RINGf (chan, v[1]); + break; + case 1: + BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_1F(i), 1); + OUT_RINGf (chan, v[0]); + break; + default: + assert(0); + break; + } +} + +static unsigned +init_per_instance_arrays_immd(struct nv50_context *nv50, + unsigned startInstance, + unsigned pos[16], unsigned step[16]) +{ + struct nouveau_bo *bo; + unsigned i, b, count = 0; + + for (i = 0; i < nv50->vtxelt_nr; ++i) { + if (!nv50->vtxelt[i].instance_divisor) + continue; + ++count; + b = nv50->vtxelt[i].vertex_buffer_index; + + pos[i] = nv50->vtxelt[i].src_offset + + nv50->vtxbuf[b].buffer_offset + + startInstance * nv50->vtxbuf[b].stride; + step[i] = startInstance % nv50->vtxelt[i].instance_divisor; + + bo = nouveau_bo(nv50->vtxbuf[b].buffer); + if (!bo->map) + nouveau_bo_map(bo, NOUVEAU_BO_RD); + + nv50_set_static_vtxattr(nv50, i, (uint8_t *)bo->map + pos[i]); + } + + return count; +} + +static unsigned +init_per_instance_arrays(struct nv50_context *nv50, + unsigned startInstance, + unsigned pos[16], unsigned step[16]) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + struct nouveau_bo *bo; + struct nouveau_stateobj *so; + unsigned i, b, count = 0; + const uint32_t rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; + + if (nv50->vbo_fifo) + return init_per_instance_arrays_immd(nv50, startInstance, + pos, step); + + so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 2, nv50->vtxelt_nr * 2); + + for (i = 0; i < nv50->vtxelt_nr; ++i) { + if (!nv50->vtxelt[i].instance_divisor) + continue; + ++count; + b = nv50->vtxelt[i].vertex_buffer_index; + + pos[i] = nv50->vtxelt[i].src_offset + + nv50->vtxbuf[b].buffer_offset + + startInstance * nv50->vtxbuf[b].stride; + + if (!startInstance) { + step[i] = 0; + continue; + } + step[i] = startInstance % nv50->vtxelt[i].instance_divisor; + + bo = nouveau_bo(nv50->vtxbuf[b].buffer); + + so_method(so, tesla, NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2); + so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_LOW, 0, 0); + } + + if (count && startInstance) { + so_ref (so, &nv50->state.instbuf); /* for flush notify */ + so_emit(chan, nv50->state.instbuf); + } + so_ref (NULL, &so); + + return count; +} + +static void +step_per_instance_arrays_immd(struct nv50_context *nv50, + unsigned pos[16], unsigned step[16]) +{ + struct nouveau_bo *bo; + unsigned i, b; + + for (i = 0; i < nv50->vtxelt_nr; ++i) { + if (!nv50->vtxelt[i].instance_divisor) + continue; + if (++step[i] != nv50->vtxelt[i].instance_divisor) + continue; + b = nv50->vtxelt[i].vertex_buffer_index; + bo = nouveau_bo(nv50->vtxbuf[b].buffer); + + step[i] = 0; + pos[i] += nv50->vtxbuf[b].stride; + + nv50_set_static_vtxattr(nv50, i, (uint8_t *)bo->map + pos[i]); + } +} + +static void +step_per_instance_arrays(struct nv50_context *nv50, + unsigned pos[16], unsigned step[16]) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + struct nouveau_bo *bo; + struct nouveau_stateobj *so; + unsigned i, b; + const uint32_t rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; + + if (nv50->vbo_fifo) { + step_per_instance_arrays_immd(nv50, pos, step); + return; + } + + so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 2, nv50->vtxelt_nr * 2); + + for (i = 0; i < nv50->vtxelt_nr; ++i) { + if (!nv50->vtxelt[i].instance_divisor) + continue; + b = nv50->vtxelt[i].vertex_buffer_index; + + if (++step[i] == nv50->vtxelt[i].instance_divisor) { + step[i] = 0; + pos[i] += nv50->vtxbuf[b].stride; + } + + bo = nouveau_bo(nv50->vtxbuf[b].buffer); + + so_method(so, tesla, NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2); + so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_LOW, 0, 0); + } + + so_ref (so, &nv50->state.instbuf); /* for flush notify */ + so_ref (NULL, &so); + + so_emit(chan, nv50->state.instbuf); +} + +static INLINE void +nv50_unmap_vbufs(struct nv50_context *nv50) +{ + unsigned i; + + for (i = 0; i < nv50->vtxbuf_nr; ++i) + if (nouveau_bo(nv50->vtxbuf[i].buffer)->map) + nouveau_bo_unmap(nouveau_bo(nv50->vtxbuf[i].buffer)); +} + +void +nv50_draw_arrays_instanced(struct pipe_context *pipe, + unsigned mode, unsigned start, unsigned count, + unsigned startInstance, unsigned instanceCount) +{ + struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_channel *chan = nv50->screen->tesla->channel; + struct nouveau_grobj *tesla = nv50->screen->tesla; + unsigned i, nz_divisors; + unsigned step[16], pos[16]; + + if (!NV50_USING_LOATHED_EDGEFLAG(nv50)) + nv50_upload_user_vbufs(nv50); + + nv50_state_validate(nv50); + + nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step); + + BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); + OUT_RING (chan, NV50_CB_AUX | (24 << 8)); + OUT_RING (chan, startInstance); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(mode)); + + if (nv50->vbo_fifo) + nv50_push_arrays(nv50, start, count); + else { + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); + OUT_RING (chan, start); + OUT_RING (chan, count); + } + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + + for (i = 1; i < instanceCount; i++) { + if (nz_divisors) /* any non-zero array divisors ? */ + step_per_instance_arrays(nv50, pos, step); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(mode) | (1 << 28)); + + if (nv50->vbo_fifo) + nv50_push_arrays(nv50, start, count); + else { + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); + OUT_RING (chan, start); + OUT_RING (chan, count); + } + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + } + nv50_unmap_vbufs(nv50); + + so_ref(NULL, &nv50->state.instbuf); +} + void nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) @@ -190,6 +495,8 @@ nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); OUT_RING (chan, 0); + nv50_unmap_vbufs(nv50); + /* XXX: not sure what to do if ret != TRUE: flush and retry? */ assert(ret); @@ -218,7 +525,7 @@ nv50_draw_elements_inline_u08(struct nv50_context *nv50, uint8_t *map, unsigned nr = count > 2046 ? 2046 : count; int i; - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16 | 0x40000000, nr >> 1); + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, nr >> 1); for (i = 0; i < nr; i += 2) OUT_RING (chan, (map[i + 1] << 16) | map[i]); @@ -251,7 +558,7 @@ nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map, unsigned nr = count > 2046 ? 2046 : count; int i; - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16 | 0x40000000, nr >> 1); + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, nr >> 1); for (i = 0; i < nr; i += 2) OUT_RING (chan, (map[i + 1] << 16) | map[i]); @@ -276,7 +583,7 @@ nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint32_t *map, while (count) { unsigned nr = count > 2047 ? 2047 : count; - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32 | 0x40000000, nr); + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U32, nr); OUT_RINGp (chan, map, nr); count -= nr; @@ -285,6 +592,77 @@ nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint32_t *map, return TRUE; } +static INLINE void +nv50_draw_elements_inline(struct nv50_context *nv50, + void *map, unsigned indexSize, + unsigned start, unsigned count) +{ + switch (indexSize) { + case 1: + nv50_draw_elements_inline_u08(nv50, map, start, count); + break; + case 2: + nv50_draw_elements_inline_u16(nv50, map, start, count); + break; + case 4: + nv50_draw_elements_inline_u32(nv50, map, start, count); + break; + } +} + +void +nv50_draw_elements_instanced(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, unsigned count, + unsigned startInstance, unsigned instanceCount) +{ + struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + struct pipe_screen *pscreen = pipe->screen; + void *map; + unsigned i, nz_divisors; + unsigned step[16], pos[16]; + + map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); + + if (!NV50_USING_LOATHED_EDGEFLAG(nv50)) + nv50_upload_user_vbufs(nv50); + + nv50_state_validate(nv50); + + nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step); + + BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); + OUT_RING (chan, NV50_CB_AUX | (24 << 8)); + OUT_RING (chan, startInstance); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(mode)); + + nv50_draw_elements_inline(nv50, map, indexSize, start, count); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + + for (i = 1; i < instanceCount; ++i) { + if (nz_divisors) /* any non-zero array divisors ? */ + step_per_instance_arrays(nv50, pos, step); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(mode) | (1 << 28)); + + nv50_draw_elements_inline(nv50, map, indexSize, start, count); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + } + nv50_unmap_vbufs(nv50); + + so_ref(NULL, &nv50->state.instbuf); +} + void nv50_draw_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, @@ -295,7 +673,6 @@ nv50_draw_elements(struct pipe_context *pipe, struct nouveau_grobj *tesla = nv50->screen->tesla; struct pipe_screen *pscreen = pipe->screen; void *map; - boolean ret; map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); @@ -308,29 +685,15 @@ nv50_draw_elements(struct pipe_context *pipe, BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); OUT_RING (chan, nv50_prim(mode)); - switch (indexSize) { - case 1: - ret = nv50_draw_elements_inline_u08(nv50, map, start, count); - break; - case 2: - ret = nv50_draw_elements_inline_u16(nv50, map, start, count); - break; - case 4: - ret = nv50_draw_elements_inline_u32(nv50, map, start, count); - break; - default: - assert(0); - ret = FALSE; - break; - } + + nv50_draw_elements_inline(nv50, map, indexSize, start, count); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); OUT_RING (chan, 0); + nv50_unmap_vbufs(nv50); + pipe_buffer_unmap(pscreen, indexBuffer); - - /* XXX: what to do if ret != TRUE? Flush and retry? - */ - assert(ret); } static INLINE boolean @@ -343,23 +706,16 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, struct nouveau_stateobj *so; struct nouveau_grobj *tesla = nv50->screen->tesla; struct nouveau_bo *bo = nouveau_bo(vb->buffer); - float *v; + float v[4]; int ret; - enum pipe_format pf = ve->src_format; - const struct util_format_description *desc; - - desc = util_format_description(pf); - assert(desc); - - if ((desc->channel[0].type != UTIL_FORMAT_TYPE_FLOAT) || - util_format_get_component_bits(pf, UTIL_FORMAT_COLORSPACE_RGB, 0) != 32) - return FALSE; ret = nouveau_bo_map(bo, NOUVEAU_BO_RD); if (ret) return FALSE; - v = (float *)(bo->map + (vb->buffer_offset + ve->src_offset)); + util_format_read_4f(ve->src_format, v, 0, (uint8_t *)bo->map + + (vb->buffer_offset + ve->src_offset), 0, + 0, 0, 1, 1); so = *pso; if (!so) *pso = so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 4, 0); @@ -417,7 +773,7 @@ nv50_vbo_validate(struct nv50_context *nv50) !(nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX)) nv50->vbo_fifo = 0xffff; - if (nv50->vertprog->cfg.edgeflag_in < 16) + if (NV50_USING_LOATHED_EDGEFLAG(nv50)) nv50->vbo_fifo = 0xffff; /* vertprog can't set edgeflag */ n_ve = MAX2(nv50->vtxelt_nr, nv50->state.vtxelt_nr); @@ -445,17 +801,20 @@ nv50_vbo_validate(struct nv50_context *nv50) nv50->vbo_fifo &= ~(1 << i); continue; } - so_data(vtxfmt, hw | i); if (nv50->vbo_fifo) { + so_data (vtxfmt, hw | + (ve->instance_divisor ? (1 << 4) : i)); so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 1); so_data (vtxbuf, 0); continue; } + so_data(vtxfmt, hw | i); so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 3); - so_data (vtxbuf, 0x20000000 | vb->stride); + so_data (vtxbuf, 0x20000000 | + (ve->instance_divisor ? 0 : vb->stride)); so_reloc (vtxbuf, bo, vb->buffer_offset + ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); @@ -493,7 +852,7 @@ typedef void (*pfn_push)(struct nouveau_channel *, void *); struct nv50_vbo_emitctx { pfn_push push[16]; - void *map[16]; + uint8_t *map[16]; unsigned stride[16]; unsigned nr_ve; unsigned vtx_dwords; @@ -531,19 +890,18 @@ nv50_map_vbufs(struct nv50_context *nv50) for (i = 0; i < nv50->vtxbuf_nr; ++i) { struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i]; - unsigned size, delta; + unsigned size = vb->stride * (vb->max_index + 1) + 16; if (nouveau_bo(vb->buffer)->map) continue; - size = vb->stride * (vb->max_index + 1); - delta = vb->buffer_offset; - + size = vb->stride * (vb->max_index + 1) + 16; + size = MIN2(size, vb->buffer->size); if (!size) - size = vb->buffer->size - vb->buffer_offset; + size = vb->buffer->size; if (nouveau_bo_map_range(nouveau_bo(vb->buffer), - delta, size, NOUVEAU_BO_RD)) + 0, size, NOUVEAU_BO_RD)) break; } @@ -554,16 +912,6 @@ nv50_map_vbufs(struct nv50_context *nv50) return FALSE; } -static INLINE void -nv50_unmap_vbufs(struct nv50_context *nv50) -{ - unsigned i; - - for (i = 0; i < nv50->vtxbuf_nr; ++i) - if (nouveau_bo(nv50->vtxbuf[i].buffer)->map) - nouveau_bo_unmap(nouveau_bo(nv50->vtxbuf[i].buffer)); -} - static void emit_b32_1(struct nouveau_channel *chan, void *data) { @@ -658,12 +1006,13 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit, ve = &nv50->vtxelt[i]; vb = &nv50->vtxbuf[ve->vertex_buffer_index]; - if (!(nv50->vbo_fifo & (1 << i))) + if (!(nv50->vbo_fifo & (1 << i)) || ve->instance_divisor) continue; n = emit->nr_ve++; emit->stride[n] = vb->stride; - emit->map[n] = nouveau_bo(vb->buffer)->map + + emit->map[n] = (uint8_t *)nouveau_bo(vb->buffer)->map + + vb->buffer_offset + (start * vb->stride + ve->src_offset); desc = util_format_description(ve->src_format); @@ -753,13 +1102,12 @@ nv50_push_arrays(struct nv50_context *nv50, unsigned start, unsigned count) set_edgeflag(chan, tesla, &emit, 0); /* nr will be 1 */ - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); + BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); for (i = 0; i < nr; ++i) emit_vtx_next(chan, &emit); count -= nr; } - nv50_unmap_vbufs(nv50); return TRUE; } @@ -780,13 +1128,12 @@ nv50_push_elements_u32(struct nv50_context *nv50, uint32_t *map, unsigned count) set_edgeflag(chan, tesla, &emit, *map); - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); + BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); for (i = 0; i < nr; ++i) emit_vtx(chan, &emit, *map++); count -= nr; } - nv50_unmap_vbufs(nv50); return TRUE; } @@ -807,13 +1154,12 @@ nv50_push_elements_u16(struct nv50_context *nv50, uint16_t *map, unsigned count) set_edgeflag(chan, tesla, &emit, *map); - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); + BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); for (i = 0; i < nr; ++i) emit_vtx(chan, &emit, *map++); count -= nr; } - nv50_unmap_vbufs(nv50); return TRUE; } @@ -834,13 +1180,12 @@ nv50_push_elements_u08(struct nv50_context *nv50, uint8_t *map, unsigned count) set_edgeflag(chan, tesla, &emit, *map); - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); + BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); for (i = 0; i < nr; ++i) emit_vtx(chan, &emit, *map++); count -= nr; } - nv50_unmap_vbufs(nv50); return TRUE; } diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index c14414fff6..cdedb30220 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -23,8 +23,6 @@ #include "r300_blit.h" #include "r300_context.h" -#include "util/u_rect.h" - static void r300_blitter_save_states(struct r300_context* r300) { util_blitter_save_blend(r300->blitter, r300->blend_state.state); @@ -75,13 +73,15 @@ void r300_clear(struct pipe_context* pipe, */ struct r300_context* r300 = r300_context(pipe); + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; r300_blitter_save_states(r300); util_blitter_clear(r300->blitter, - r300->framebuffer_state.width, - r300->framebuffer_state.height, - r300->framebuffer_state.nr_cbufs, + fb->width, + fb->height, + fb->nr_cbufs, buffers, rgba, depth, stencil); } @@ -99,7 +99,7 @@ void r300_surface_copy(struct pipe_context* pipe, * is really transparent. The states will be restored by the blitter once * copying is done. */ r300_blitter_save_states(r300); - util_blitter_save_framebuffer(r300->blitter, &r300->framebuffer_state); + util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); util_blitter_save_fragment_sampler_states( r300->blitter, r300->sampler_count, (void**)r300->sampler_states); @@ -123,7 +123,7 @@ void r300_surface_fill(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); r300_blitter_save_states(r300); - util_blitter_save_framebuffer(r300->blitter, &r300->framebuffer_state); + util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); util_blitter_fill(r300->blitter, dst, dstx, dsty, width, height, value); diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 5e4f6552c3..9837530a7a 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -22,9 +22,6 @@ #include "draw/draw_context.h" -#include "tgsi/tgsi_scan.h" - -#include "util/u_hash_table.h" #include "util/u_memory.h" #include "util/u_simple_list.h" @@ -35,30 +32,16 @@ #include "r300_query.h" #include "r300_render.h" #include "r300_screen.h" -#include "r300_state_derived.h" #include "r300_state_invariant.h" #include "r300_texture.h" #include "r300_winsys.h" -static enum pipe_error r300_clear_hash_table(void* key, void* value, - void* data) -{ - FREE(key); - FREE(value); - return PIPE_OK; -} - static void r300_destroy_context(struct pipe_context* context) { struct r300_context* r300 = r300_context(context); struct r300_query* query, * temp; util_blitter_destroy(r300->blitter); - - util_hash_table_foreach(r300->shader_hash_table, r300_clear_hash_table, - NULL); - util_hash_table_destroy(r300->shader_hash_table); - draw_destroy(r300->draw); /* Free the OQ BO. */ @@ -72,9 +55,9 @@ static void r300_destroy_context(struct pipe_context* context) FREE(r300->blend_color_state.state); FREE(r300->clip_state.state); - FREE(r300->rs_block); + FREE(r300->rs_block_state.state); FREE(r300->scissor_state.state); - FREE(r300->vertex_info); + FREE(r300->vertex_format_state.state); FREE(r300->viewport_state.state); FREE(r300->ztop_state.state); FREE(r300); @@ -87,7 +70,7 @@ r300_is_texture_referenced(struct pipe_context *pipe, { struct pipe_buffer* buf = 0; - r300_get_texture_buffer(texture, &buf, NULL); + r300_get_texture_buffer(pipe->screen, texture, &buf, NULL); return pipe->is_buffer_referenced(pipe, buf); } @@ -129,14 +112,18 @@ static void r300_setup_atoms(struct r300_context* r300) * an upper bound on each atom, to keep the emission machinery from * underallocating space. */ make_empty_list(&r300->atom_list); + R300_INIT_ATOM(invariant, 71); R300_INIT_ATOM(ztop, 2); R300_INIT_ATOM(blend, 8); R300_INIT_ATOM(blend_color, 3); R300_INIT_ATOM(clip, 29); R300_INIT_ATOM(dsa, 8); - R300_INIT_ATOM(rs, 22); + R300_INIT_ATOM(fb, 56); + R300_INIT_ATOM(rs, 25); R300_INIT_ATOM(scissor, 3); R300_INIT_ATOM(viewport, 9); + R300_INIT_ATOM(rs_block, 21); + R300_INIT_ATOM(vertex_format, 26); } struct pipe_context* r300_create_context(struct pipe_screen* screen, @@ -153,8 +140,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->context.winsys = (struct pipe_winsys*)radeon_winsys; r300->context.screen = screen; - r300_init_debug(r300); - r300->context.destroy = r300_destroy_context; r300->context.clear = r300_clear; @@ -184,16 +169,13 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->context.is_texture_referenced = r300_is_texture_referenced; r300->context.is_buffer_referenced = r300_is_buffer_referenced; - r300->shader_hash_table = util_hash_table_create(r300_shader_key_hash, - r300_shader_key_compare); - r300_setup_atoms(r300); r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state); r300->clip_state.state = CALLOC_STRUCT(pipe_clip_state); - r300->rs_block = CALLOC_STRUCT(r300_rs_block); + r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block); r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state); - r300->vertex_info = CALLOC_STRUCT(r300_vertex_info); + r300->vertex_format_state.state = CALLOC_STRUCT(r300_vertex_info); r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state); r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state); @@ -210,7 +192,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300_init_state_functions(r300); - r300_emit_invariant_state(r300); + r300->invariant_state.dirty = TRUE; r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300); r300->dirty_state = R300_NEW_KITCHEN_SINK; diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 682b9179c8..3f461640a0 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -30,6 +30,8 @@ #include "pipe/p_context.h" #include "pipe/p_inlines.h" +#include "r300_screen.h" + struct r300_context; struct r300_fragment_shader; @@ -82,13 +84,14 @@ struct r300_rs_state { struct pipe_rasterizer_state rs; 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 */ - uint32_t depth_scale_front; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */ - uint32_t depth_offset_front;/* R300_SU_POLY_OFFSET_FRONT_OFFSET: 0x42a8 */ - uint32_t depth_scale_back; /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */ - uint32_t depth_offset_back; /* R300_SU_POLY_OFFSET_BACK_OFFSET: 0x42b0 */ + float depth_scale; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */ + /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */ + float depth_offset; /* R300_SU_POLY_OFFSET_FRONT_OFFSET: 0x42a8 */ + /* R300_SU_POLY_OFFSET_BACK_OFFSET: 0x42b0 */ uint32_t polygon_offset_enable; /* R300_SU_POLY_OFFSET_ENABLE: 0x42b4 */ uint32_t cull_mode; /* R300_SU_CULL_MODE: 0x42b8 */ uint32_t line_stipple_config; /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */ @@ -136,15 +139,12 @@ struct r300_ztop_state { uint32_t z_buffer_top; /* R300_ZB_ZTOP: 0x4f14 */ }; -#define R300_NEW_FRAMEBUFFERS 0x00000010 #define R300_NEW_FRAGMENT_SHADER 0x00000020 #define R300_NEW_FRAGMENT_SHADER_CONSTANTS 0x00000040 -#define R300_NEW_RS_BLOCK 0x00000100 #define R300_NEW_SAMPLER 0x00000200 #define R300_ANY_NEW_SAMPLERS 0x0001fe00 #define R300_NEW_TEXTURE 0x00040000 #define R300_ANY_NEW_TEXTURES 0x03fc0000 -#define R300_NEW_VERTEX_FORMAT 0x04000000 #define R300_NEW_VERTEX_SHADER 0x08000000 #define R300_NEW_VERTEX_SHADER_CONSTANTS 0x10000000 #define R300_NEW_QUERY 0x40000000 @@ -269,11 +269,8 @@ struct r300_context { struct r300_query *query_current; struct r300_query query_list; - /* Shader hash table. Used to store vertex formatting information, which - * depends on the combination of both currently loaded shaders. */ - struct util_hash_table* shader_hash_table; /* Vertex formatting information. */ - struct r300_vertex_info* vertex_info; + struct r300_atom vertex_format_state; /* Various CSO state objects. */ /* Beginning of atom list. */ @@ -290,12 +287,12 @@ struct r300_context { struct r300_atom dsa_state; /* Fragment shader. */ struct r300_fragment_shader* fs; - /* Framebuffer state. We currently don't need our own version of this. */ - struct pipe_framebuffer_state framebuffer_state; + /* Framebuffer state. */ + struct r300_atom fb_state; /* Rasterizer state. */ struct r300_atom rs_state; /* RS block state. */ - struct r300_rs_block* rs_block; + struct r300_atom rs_block_state; /* Sampler states. */ struct r300_sampler_state* sampler_states[8]; int sampler_count; @@ -311,6 +308,9 @@ struct r300_context { /* ZTOP state. */ struct r300_atom ztop_state; + /* Invariant state. This must be emitted to get the engine started. */ + struct r300_atom invariant_state; + /* Vertex buffers for Gallium. */ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; int vertex_buffer_count; @@ -324,9 +324,10 @@ struct r300_context { uint32_t dirty_hw; /* Whether the TCL engine should be in bypass mode. */ boolean tcl_bypass; - - /** Combination of DBG_xxx flags */ - unsigned debug; + /* Whether polygon offset is enabled. */ + boolean polygon_offset_enabled; + /* Z buffer bit depth. */ + uint32_t zbuffer_bpp; }; /* Convenience cast wrapper. */ @@ -340,35 +341,15 @@ struct draw_stage* r300_draw_stage(struct r300_context* r300); void r300_init_state_functions(struct r300_context* r300); void r300_init_surface_functions(struct r300_context* r300); -/* Debug functionality. */ - -/** - * Debug flags to disable/enable certain groups of debugging outputs. - * - * \note These may be rather coarse, and the grouping may be impractical. - * If you find, while debugging the driver, that a different grouping - * of these flags would be beneficial, just feel free to change them - * but make sure to update the documentation in r300_debug.c to reflect - * 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 -/*@}*/ - -static INLINE boolean DBG_ON(struct r300_context * ctx, unsigned flags) +static INLINE boolean CTX_DBG_ON(struct r300_context * ctx, unsigned flags) { - return (ctx->debug & flags) ? TRUE : FALSE; + return SCREEN_DBG_ON(r300_screen(ctx->context.screen), flags); } -static INLINE void DBG(struct r300_context * ctx, unsigned flags, const char * fmt, ...) +static INLINE void CTX_DBG(struct r300_context * ctx, unsigned flags, + const char * fmt, ...) { - if (DBG_ON(ctx, flags)) { + if (CTX_DBG_ON(ctx, flags)) { va_list va; va_start(va, fmt); debug_vprintf(fmt, va); @@ -376,6 +357,8 @@ static INLINE void DBG(struct r300_context * ctx, unsigned flags, const char * f } } -void r300_init_debug(struct r300_context * ctx); +#define DBG_ON CTX_DBG_ON +#define DBG CTX_DBG #endif /* R300_CONTEXT_H */ + diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index 2a6ed54ac9..b881730848 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -22,8 +22,6 @@ #include "r300_context.h" -#include <ctype.h> - struct debug_option { const char * name; @@ -46,7 +44,7 @@ static struct debug_option debug_options[] = { { 0, 0, 0 } }; -void r300_init_debug(struct r300_context * ctx) +void r300_init_debug(struct r300_screen * screen) { const char * options = debug_get_option("RADEON_DEBUG", 0); boolean printhint = FALSE; @@ -64,7 +62,7 @@ void r300_init_debug(struct r300_context * ctx) for(opt = debug_options; opt->name; ++opt) { if (!strncmp(options, opt->name, length)) { - ctx->debug |= opt->flag; + screen->debug |= opt->flag; break; } } @@ -77,11 +75,11 @@ void r300_init_debug(struct r300_context * ctx) options += length; } - if (!ctx->debug) + if (!screen->debug) printhint = TRUE; } - if (printhint || ctx->debug & DBG_HELP) { + if (printhint || screen->debug & DBG_HELP) { debug_printf("You can enable debug output by setting the RADEON_DEBUG environment variable\n" "to a comma-separated list of debug options. Available options are:\n"); for(opt = debug_options; opt->name; ++opt) { diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 9f93327e59..a429457625 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -32,20 +32,20 @@ #include "r300_emit.h" #include "r300_fs.h" #include "r300_screen.h" -#include "r300_state_derived.h" #include "r300_state_inlines.h" -#include "r300_texture.h" #include "r300_vs.h" void r300_emit_blend_state(struct r300_context* r300, void* state) { struct r300_blend_state* blend = (struct r300_blend_state*)state; + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; CS_LOCALS(r300); BEGIN_CS(8); OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop); OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 3); - if (r300->framebuffer_state.nr_cbufs) { + if (fb->nr_cbufs) { OUT_CS(blend->blend_control); OUT_CS(blend->alpha_blend_control); OUT_CS(blend->color_channel_mask); @@ -112,6 +112,8 @@ void r300_emit_dsa_state(struct r300_context* r300, void* state) { struct r300_dsa_state* dsa = (struct r300_dsa_state*)state; struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; CS_LOCALS(r300); BEGIN_CS(r300screen->caps->is_r500 ? 8 : 6); @@ -124,7 +126,7 @@ void r300_emit_dsa_state(struct r300_context* r300, void* state) OUT_CS_REG_SEQ(R300_ZB_CNTL, 3); - if (r300->framebuffer_state.zsbuf) { + if (fb->zsbuf) { OUT_CS(dsa->z_buffer_control); OUT_CS(dsa->z_stencil_control); } else { @@ -168,9 +170,8 @@ static const float * get_shader_constant( vec[1] = 1.0 / tex->height0; break; - /* Texture compare-fail value. */ - /* XXX Since Gallium doesn't support GL_ARB_shadow_ambient, - * this is always (0,0,0,0), right? */ + /* Texture compare-fail value. Shouldn't ever show up, but if + * it does, we'll be ready. */ case RC_STATE_SHADOW_AMBIENT: vec[3] = 0; break; @@ -384,17 +385,14 @@ void r500_emit_fs_constant_buffer(struct r300_context* r300, END_CS; } -void r300_emit_fb_state(struct r300_context* r300, - struct pipe_framebuffer_state* fb) +void r300_emit_fb_state(struct r300_context* r300, void* state) { + struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state; struct r300_texture* tex; struct pipe_surface* surf; int i; CS_LOCALS(r300); - /* Shouldn't fail unless there is a bug in the state tracker. */ - assert(fb->nr_cbufs <= 4); - BEGIN_CS((10 * fb->nr_cbufs) + (2 * (4 - fb->nr_cbufs)) + (fb->zsbuf ? 10 : 0) + 6); @@ -407,7 +405,14 @@ void r300_emit_fb_state(struct r300_context* r300, R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); /* Set the number of colorbuffers. */ - OUT_CS_REG(R300_RB3D_CCTL, R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs)); + if (fb->nr_cbufs > 1) { + OUT_CS_REG(R300_RB3D_CCTL, + R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs) | + R300_RB3D_CCTL_INDEPENDENT_COLOR_CHANNEL_MASK_ENABLE | + R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE); + } else { + OUT_CS_REG(R300_RB3D_CCTL, 0x0); + } /* Set up colorbuffers. */ for (i = 0; i < fb->nr_cbufs; i++) { @@ -584,19 +589,40 @@ void r300_emit_query_end(struct r300_context* r300) void r300_emit_rs_state(struct r300_context* r300, void* state) { struct r300_rs_state* rs = (struct r300_rs_state*)state; + float scale, offset; CS_LOCALS(r300); - BEGIN_CS(22); + BEGIN_CS(20 + (rs->polygon_offset_enable ? 5 : 0)); OUT_CS_REG(R300_VAP_CNTL_STATUS, rs->vap_control_status); + + OUT_CS_REG(R300_GB_AA_CONFIG, rs->antialiasing_config); + OUT_CS_REG(R300_GA_POINT_SIZE, rs->point_size); OUT_CS_REG_SEQ(R300_GA_POINT_MINMAX, 2); OUT_CS(rs->point_minmax); OUT_CS(rs->line_control); - OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 6); - OUT_CS(rs->depth_scale_front); - OUT_CS(rs->depth_offset_front); - OUT_CS(rs->depth_scale_back); - OUT_CS(rs->depth_offset_back); + + if (rs->polygon_offset_enable) { + scale = rs->depth_scale * 12; + offset = rs->depth_offset; + + switch (r300->zbuffer_bpp) { + case 16: + offset *= 4; + break; + case 24: + offset *= 2; + break; + } + + OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4); + OUT_CS_32F(scale); + OUT_CS_32F(offset); + OUT_CS_32F(scale); + OUT_CS_32F(offset); + } + + OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_ENABLE, 2); OUT_CS(rs->polygon_offset_enable); OUT_CS(rs->cull_mode); OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config); @@ -606,10 +632,10 @@ void r300_emit_rs_state(struct r300_context* r300, void* state) END_CS; } -void r300_emit_rs_block_state(struct r300_context* r300, - struct r300_rs_block* rs) +void r300_emit_rs_block_state(struct r300_context* r300, void* state) { - int i; + struct r300_rs_block* rs = (struct r300_rs_block*)state; + unsigned i; struct r300_screen* r300screen = r300_screen(r300->context.screen); CS_LOCALS(r300); @@ -652,11 +678,13 @@ void r300_emit_scissor_state(struct r300_context* r300, void* state) uint32_t top_left, bottom_right; struct r300_screen* r300screen = r300_screen(r300->context.screen); struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state; + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; CS_LOCALS(r300); minx = miny = 0; - maxx = r300->framebuffer_state.width; - maxy = r300->framebuffer_state.height; + maxx = fb->width; + maxy = fb->height; if (((struct r300_rs_state*)r300->rs_state.state)->rs.scissor) { minx = MAX2(minx, scissor->minx); @@ -665,6 +693,22 @@ void r300_emit_scissor_state(struct r300_context* r300, void* state) maxy = MIN2(maxy, scissor->maxy); } + /* Special case for zero-area scissor. + * + * We can't allow the variables maxx and maxy to be zero because they are + * subtracted from later in the code, which would cause emitting ~0 and + * making the kernel checker angry. + * + * Let's consider we change maxx and maxy to 1, which is effectively + * a one-pixel area. We must then change minx and miny to a number which is + * greater than 1 to get the zero area back. */ + if (!maxx || !maxy) { + minx = 2; + miny = 2; + maxx = 1; + maxy = 1; + } + if (r300screen->caps->is_r500) { top_left = (minx << R300_SCISSORS_X_SHIFT) | @@ -705,12 +749,18 @@ void r300_emit_texture(struct r300_context* r300, filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); } - /* determine min/max levels */ - /* the MAX_MIP level is the largest (finest) one */ - max_level = MIN2(sampler->max_lod, tex->tex.last_level); - min_level = MIN2(sampler->min_lod, max_level); - format0 |= R300_TX_NUM_LEVELS(max_level); - filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); + if (tex->is_npot) { + /* NPOT textures don't support mip filter, unfortunately. + * This prevents incorrect rendering. */ + filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK; + } else { + /* determine min/max levels */ + /* the MAX_MIP level is the largest (finest) one */ + max_level = MIN2(sampler->max_lod, tex->tex.last_level); + min_level = MIN2(sampler->min_lod, max_level); + format0 |= R300_TX_NUM_LEVELS(max_level); + filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); + } BEGIN_CS(16); OUT_CS_REG(R300_TX_FILTER0_0 + (offset * 4), filter0 | @@ -729,22 +779,6 @@ void r300_emit_texture(struct r300_context* r300, END_CS; } -static boolean r300_validate_aos(struct r300_context *r300) -{ - struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->vertex_element; - int i; - - /* Check if formats and strides are aligned to the size of DWORD. */ - for (i = 0; i < r300->vertex_element_count; i++) { - if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 || - util_format_get_blocksize(velem[i].src_format) % 4 != 0) { - return FALSE; - } - } - return TRUE; -} - void r300_emit_aos(struct r300_context* r300, unsigned offset) { struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer; @@ -754,12 +788,6 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset) unsigned packet_size = (aos_count * 3 + 1) / 2; CS_LOCALS(r300); - /* XXX Move this checking to a more approriate place. */ - if (!r300_validate_aos(r300)) { - /* XXX We should fallback using Draw. */ - assert(0); - } - BEGIN_CS(2 + packet_size + aos_count * 2); OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); OUT_CS(aos_count); @@ -791,38 +819,39 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset) END_CS; } -void r300_emit_vertex_format_state(struct r300_context* r300) +void r300_emit_vertex_format_state(struct r300_context* r300, void* state) { - int i; + struct r300_vertex_info* vertex_info = (struct r300_vertex_info*)state; + unsigned i; CS_LOCALS(r300); DBG(r300, DBG_DRAW, "r300: VAP/PSC emit:\n"); BEGIN_CS(26); - OUT_CS_REG(R300_VAP_VTX_SIZE, r300->vertex_info->vinfo.size); + OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_info->vinfo.size); OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2); - OUT_CS(r300->vertex_info->vinfo.hwfmt[0]); - OUT_CS(r300->vertex_info->vinfo.hwfmt[1]); + OUT_CS(vertex_info->vinfo.hwfmt[0]); + OUT_CS(vertex_info->vinfo.hwfmt[1]); OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2); - OUT_CS(r300->vertex_info->vinfo.hwfmt[2]); - OUT_CS(r300->vertex_info->vinfo.hwfmt[3]); + OUT_CS(vertex_info->vinfo.hwfmt[2]); + OUT_CS(vertex_info->vinfo.hwfmt[3]); for (i = 0; i < 4; i++) { DBG(r300, DBG_DRAW, " : hwfmt%d: 0x%08x\n", i, - r300->vertex_info->vinfo.hwfmt[i]); + vertex_info->vinfo.hwfmt[i]); } OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, 8); for (i = 0; i < 8; i++) { - OUT_CS(r300->vertex_info->vap_prog_stream_cntl[i]); + OUT_CS(vertex_info->vap_prog_stream_cntl[i]); DBG(r300, DBG_DRAW, " : prog_stream_cntl%d: 0x%08x\n", i, - r300->vertex_info->vap_prog_stream_cntl[i]); + vertex_info->vap_prog_stream_cntl[i]); } OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, 8); for (i = 0; i < 8; i++) { - OUT_CS(r300->vertex_info->vap_prog_stream_cntl_ext[i]); + OUT_CS(vertex_info->vap_prog_stream_cntl_ext[i]); DBG(r300, DBG_DRAW, " : prog_stream_cntl_ext%d: 0x%08x\n", i, - r300->vertex_info->vap_prog_stream_cntl_ext[i]); + vertex_info->vap_prog_stream_cntl_ext[i]); } END_CS; } @@ -987,39 +1016,21 @@ static void r300_flush_pvs(struct r300_context* r300) END_CS; } -/* Emit all dirty state. */ -void r300_emit_dirty_state(struct r300_context* r300) +void r300_emit_buffer_validate(struct r300_context *r300) { - struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; struct r300_texture* tex; - struct r300_atom* atom; - unsigned i, dwords = 1024; - int dirty_tex = 0; + unsigned i; boolean invalid = FALSE; - /* Check the required number of dwords against the space remaining in the - * current CS object. If we need more, then flush. */ - - foreach(atom, &r300->atom_list) { - if (atom->dirty || atom->always_dirty) { - dwords += atom->size; - } - } - - /* Make sure we have at least 2*1024 spare dwords. */ - /* XXX It would be nice to know the number of dwords we really need to - * XXX emit. */ - if (!r300->winsys->check_cs(r300->winsys, dwords)) { - r300->context.flush(&r300->context, 0, NULL); - } - /* Clean out BOs. */ r300->winsys->reset_bos(r300->winsys); validate: /* Color buffers... */ - for (i = 0; i < r300->framebuffer_state.nr_cbufs; i++) { - tex = (struct r300_texture*)r300->framebuffer_state.cbufs[i]->texture; + for (i = 0; i < fb->nr_cbufs; i++) { + tex = (struct r300_texture*)fb->cbufs[i]->texture; assert(tex && tex->buffer && "cbuf is marked, but NULL!"); if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, 0, RADEON_GEM_DOMAIN_VRAM)) { @@ -1028,8 +1039,8 @@ validate: } } /* ...depth buffer... */ - if (r300->framebuffer_state.zsbuf) { - tex = (struct r300_texture*)r300->framebuffer_state.zsbuf->texture; + if (fb->zsbuf) { + tex = (struct r300_texture*)fb->zsbuf->texture; assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, 0, RADEON_GEM_DOMAIN_VRAM)) { @@ -1076,6 +1087,31 @@ validate: invalid = TRUE; goto validate; } +} + +/* Emit all dirty state. */ +void r300_emit_dirty_state(struct r300_context* r300) +{ + struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct r300_atom* atom; + unsigned i, dwords = 1024; + int dirty_tex = 0; + + /* Check the required number of dwords against the space remaining in the + * current CS object. If we need more, then flush. */ + + foreach(atom, &r300->atom_list) { + if (atom->dirty || atom->always_dirty) { + dwords += atom->size; + } + } + + /* Make sure we have at least 2*1024 spare dwords. */ + /* XXX It would be nice to know the number of dwords we really need to + * XXX emit. */ + while (!r300->winsys->check_cs(r300->winsys, dwords)) { + r300->context.flush(&r300->context, 0, NULL); + } if (r300->dirty_state & R300_NEW_QUERY) { r300_emit_query_start(r300); @@ -1110,16 +1146,6 @@ validate: r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER_CONSTANTS; } - if (r300->dirty_state & R300_NEW_FRAMEBUFFERS) { - r300_emit_fb_state(r300, &r300->framebuffer_state); - r300->dirty_state &= ~R300_NEW_FRAMEBUFFERS; - } - - if (r300->dirty_state & R300_NEW_RS_BLOCK) { - r300_emit_rs_block_state(r300, r300->rs_block); - r300->dirty_state &= ~R300_NEW_RS_BLOCK; - } - /* Samplers and textures are tracked separately but emitted together. */ if (r300->dirty_state & (R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES)) { @@ -1145,11 +1171,6 @@ validate: r300_flush_textures(r300); } - if (r300->dirty_state & R300_NEW_VERTEX_FORMAT) { - r300_emit_vertex_format_state(r300); - r300->dirty_state &= ~R300_NEW_VERTEX_FORMAT; - } - if (r300->dirty_state & (R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS)) { r300_flush_pvs(r300); } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index 05a6bfeae8..6b96d9b57c 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -51,8 +51,7 @@ void r500_emit_fragment_program_code(struct r300_context* r300, void r500_emit_fs_constant_buffer(struct r300_context* r300, struct rc_constant_list* constants); -void r300_emit_fb_state(struct r300_context* r300, - struct pipe_framebuffer_state* fb); +void r300_emit_fb_state(struct r300_context* r300, void* state); void r300_emit_query_begin(struct r300_context* r300, struct r300_query* query); @@ -61,8 +60,7 @@ void r300_emit_query_end(struct r300_context* r300); void r300_emit_rs_state(struct r300_context* r300, void* state); -void r300_emit_rs_block_state(struct r300_context* r300, - struct r300_rs_block* rs); +void r300_emit_rs_block_state(struct r300_context* r300, void* state); void r300_emit_scissor_state(struct r300_context* r300, void* state); @@ -73,7 +71,7 @@ void r300_emit_texture(struct r300_context* r300, void r300_emit_vertex_buffer(struct r300_context* r300); -void r300_emit_vertex_format_state(struct r300_context* r300); +void r300_emit_vertex_format_state(struct r300_context* r300, void* state); void r300_emit_vertex_program_code(struct r300_context* r300, struct r300_vertex_program_code* code); @@ -95,4 +93,6 @@ void r300_flush_textures(struct r300_context* r300); /* Emit all dirty state. */ void r300_emit_dirty_state(struct r300_context* r300); +void r300_emit_buffer_validate(struct r300_context *r300); + #endif /* R300_EMIT_H */ diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index 59819cb106..e37d309270 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -29,7 +29,6 @@ #include "r300_cs.h" #include "r300_emit.h" #include "r300_flush.h" -#include "r300_state_invariant.h" static void r300_flush(struct pipe_context* pipe, unsigned flags, @@ -53,7 +52,6 @@ static void r300_flush(struct pipe_context* pipe, if (r300->dirty_hw) { FLUSH_CS; - r300_emit_invariant_state(r300); r300->dirty_state = R300_NEW_KITCHEN_SINK; r300->dirty_hw = 0; diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 710d850163..95b7cb5fa4 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -26,10 +26,9 @@ #include "draw/draw_context.h" #include "draw/draw_vbuf.h" -#include "indices/u_indices.h" - #include "pipe/p_inlines.h" +#include "util/u_format.h" #include "util/u_memory.h" #include "util/u_prim.h" @@ -116,20 +115,60 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, return color_control; } -static void r300_emit_draw_immediate(struct r300_context *r300, - unsigned mode, - unsigned start, - unsigned count) +static boolean immd_is_good_idea(struct r300_context *r300, + unsigned count) { - struct pipe_buffer* vbo = r300->vertex_buffer[0].buffer; - unsigned vertex_size = r300->vertex_buffer[0].stride / sizeof(float); - unsigned i; - uint32_t* map; + return count <= 4; +} + +static void r300_emit_draw_arrays_immediate(struct r300_context *r300, + unsigned mode, + unsigned start, + unsigned count) +{ + struct pipe_vertex_element* velem; + struct pipe_vertex_buffer* vbuf; + unsigned vertex_element_count = r300->vertex_element_count; + unsigned i, v, vbi, dw, elem_offset; + + /* Size of the vertex, in dwords. */ + unsigned vertex_size = 0; + + /* Offsets of the attribute, in dwords, from the start of the vertex. */ + unsigned offset[PIPE_MAX_ATTRIBS]; + + /* Size of the vertex element, in dwords. */ + unsigned size[PIPE_MAX_ATTRIBS]; + + /* Stride to the same attrib in the next vertex in the vertex buffer, + * in dwords. */ + unsigned stride[PIPE_MAX_ATTRIBS]; + + /* Mapped vertex buffers. */ + uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; + CS_LOCALS(r300); - map = (uint32_t*)pipe_buffer_map_range(r300->context.screen, vbo, - start * vertex_size, count * vertex_size, - PIPE_BUFFER_USAGE_CPU_READ); + /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ + for (i = 0; i < vertex_element_count; i++) { + velem = &r300->vertex_element[i]; + offset[i] = velem->src_offset / 4; + size[i] = util_format_get_blocksize(velem->src_format) / 4; + vertex_size += size[i]; + vbi = velem->vertex_buffer_index; + + /* Map the buffer. */ + if (!map[vbi]) { + vbuf = &r300->vertex_buffer[vbi]; + map[vbi] = (uint32_t*)pipe_buffer_map(r300->context.screen, + vbuf->buffer, + PIPE_BUFFER_USAGE_CPU_READ); + map[vbi] += vbuf->buffer_offset / 4; + stride[vbi] = vbuf->stride / 4; + } + } + + r300_emit_dirty_state(r300); BEGIN_CS(10 + count * vertex_size); OUT_CS_REG(R300_GA_COLOR_CONTROL, @@ -140,18 +179,31 @@ static void r300_emit_draw_immediate(struct r300_context *r300, OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | r300_translate_primitive(mode)); - //debug_printf("r300: Immd %d verts, %d attrs\n", count, vertex_size); - for (i = 0; i < count * vertex_size; i++) { - if (i % vertex_size == 0) { - //debug_printf("r300: -- vert --\n"); + + /* Emit vertices. */ + for (v = 0; v < count; v++) { + for (i = 0; i < vertex_element_count; i++) { + velem = &r300->vertex_element[i]; + vbi = velem->vertex_buffer_index; + elem_offset = offset[i] + stride[vbi] * (v + start); + + for (dw = 0; dw < size[i]; dw++) { + OUT_CS(map[vbi][elem_offset + dw]); + } } - //debug_printf("r300: 0x%08x\n", *map); - OUT_CS(*map); - map++; } END_CS; - pipe_buffer_unmap(r300->context.screen, vbo); + /* Unmap buffers. */ + for (i = 0; i < vertex_element_count; i++) { + vbi = r300->vertex_element[i].vertex_buffer_index; + + if (map[vbi]) { + vbuf = &r300->vertex_buffer[vbi]; + pipe_buffer_unmap(r300->context.screen, vbuf->buffer); + map[vbi] = NULL; + } + } } static void r300_emit_draw_arrays(struct r300_context *r300, @@ -223,17 +275,18 @@ static void r300_emit_draw_elements(struct r300_context *r300, END_CS; } - static boolean r300_setup_vertex_buffers(struct r300_context *r300) { struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; struct pipe_vertex_element *velem = r300->vertex_element; + struct pipe_buffer *pbuf; validate: for (int i = 0; i < r300->vertex_element_count; i++) { - if (!r300->winsys->add_buffer(r300->winsys, - vbuf[velem[i].vertex_buffer_index].buffer, - RADEON_GEM_DOMAIN_GTT, 0)) { + pbuf = vbuf[velem[i].vertex_buffer_index].buffer; + + if (!r300->winsys->add_buffer(r300->winsys, pbuf, + RADEON_GEM_DOMAIN_GTT, 0)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } @@ -247,40 +300,35 @@ validate: return TRUE; } -static struct pipe_buffer* r300_translate_elts(struct r300_context* r300, - struct pipe_buffer* elts, - unsigned* size, - unsigned* mode, - unsigned* count) +static void r300_shorten_ubyte_elts(struct r300_context* r300, + struct pipe_buffer** elts, + unsigned count) { struct pipe_screen* screen = r300->context.screen; struct pipe_buffer* new_elts; - void *in_map, *out_map; - unsigned out_prim, out_index_size, out_nr; - u_translate_func out_translate; - - (void)u_index_translator(~0, *mode, *size, *count, PV_LAST, PV_LAST, - &out_prim, &out_index_size, &out_nr, &out_translate); + unsigned char *in_map; + unsigned short *out_map; + unsigned i; new_elts = screen->buffer_create(screen, 32, PIPE_BUFFER_USAGE_INDEX | PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_GPU_READ, - out_index_size * out_nr); + 2 * count); - in_map = pipe_buffer_map(screen, elts, PIPE_BUFFER_USAGE_CPU_READ); + in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ); out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE); - out_translate(in_map, *count, out_map); + for (i = 0; i < count; i++) { + *out_map = (unsigned short)*in_map; + in_map++; + out_map++; + } - pipe_buffer_unmap(screen, elts); + pipe_buffer_unmap(screen, *elts); pipe_buffer_unmap(screen, new_elts); - *size = out_index_size; - *mode = out_prim; - *count = out_nr; - - return new_elts; + *elts = new_elts; } /* This is the fast-path drawing & emission for HW TCL. */ @@ -309,13 +357,15 @@ void r300_draw_range_elements(struct pipe_context* pipe, r300_update_derived_state(r300); + r300_emit_buffer_validate(r300); + if (!r300_setup_vertex_buffers(r300)) { return; } if (indexSize == 1) { - indexBuffer = r300_translate_elts(r300, indexBuffer, - &indexSize, &mode, &count); + r300_shorten_ubyte_elts(r300, &indexBuffer, count); + indexSize = 2; } if (!r300->winsys->add_buffer(r300->winsys, indexBuffer, @@ -368,15 +418,16 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, r300_update_derived_state(r300); - if (!r300_setup_vertex_buffers(r300)) { - return; - } - - r300_emit_dirty_state(r300); + r300_emit_buffer_validate(r300); - if (FALSE && count <= 4 && r300->vertex_buffer_count == 1) { - r300_emit_draw_immediate(r300, mode, start, count); + if (immd_is_good_idea(r300, count)) { + r300_emit_draw_arrays_immediate(r300, mode, start, count); } else { + if (!r300_setup_vertex_buffers(r300)) { + return; + } + + r300_emit_dirty_state(r300); r300_emit_aos(r300, start); r300_emit_draw_arrays(r300, mode, count); } @@ -411,6 +462,7 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX, + 0, r300->shader_constants[PIPE_SHADER_VERTEX].constants, r300->shader_constants[PIPE_SHADER_VERTEX].count * (sizeof(float) * 4)); @@ -455,6 +507,7 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX, + 0, r300->shader_constants[PIPE_SHADER_VERTEX].constants, r300->shader_constants[PIPE_SHADER_VERTEX].count * (sizeof(float) * 4)); @@ -506,7 +559,7 @@ r300_render_get_vertex_info(struct vbuf_render* render) r300_update_derived_state(r300); - return &r300->vertex_info->vinfo; + return (struct vertex_info*)r300->vertex_format_state.state; } static boolean r300_render_allocate_vertices(struct vbuf_render* render, diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 287664b1d2..fa8ed581da 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -113,6 +113,8 @@ 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: @@ -149,6 +151,20 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) } else { return 0; } + case PIPE_CAP_INDEP_BLEND_ENABLE: + if (r300screen->caps->is_r500) { + return 1; + } else { + return 0; + } + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + 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; default: debug_printf("r300: Implementation error: Bad param %d\n", param); @@ -183,10 +199,20 @@ static float r300_get_paramf(struct pipe_screen* pscreen, int param) } } -static boolean check_tex_format(enum pipe_format format, uint32_t usage, - boolean is_r500) +static boolean r300_is_format_supported(struct pipe_screen* screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned usage, + unsigned geom_flags) { uint32_t retval = 0; + boolean is_r500 = r300_screen(screen)->caps->is_r500; + + if (target >= PIPE_MAX_TEXTURE_TYPES) { + debug_printf("r300: Implementation error: Received bogus texture " + "target %d in %s\n", target, __FUNCTION__); + return FALSE; + } switch (format) { /* Supported formats. */ @@ -194,6 +220,8 @@ static boolean check_tex_format(enum pipe_format format, uint32_t usage, case PIPE_FORMAT_A4R4G4B4_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: case PIPE_FORMAT_A1R5G5B5_UNORM: + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_L8_UNORM: retval = usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | @@ -208,7 +236,6 @@ static boolean check_tex_format(enum pipe_format format, uint32_t usage, case PIPE_FORMAT_DXT3_RGBA: case PIPE_FORMAT_DXT5_RGBA: case PIPE_FORMAT_YCBCR: - case PIPE_FORMAT_L8_UNORM: case PIPE_FORMAT_A8L8_UNORM: retval = usage & PIPE_TEXTURE_USAGE_SAMPLER; break; @@ -247,28 +274,13 @@ static boolean check_tex_format(enum pipe_format format, uint32_t usage, case PIPE_FORMAT_Z32_UNORM: case PIPE_FORMAT_S8Z24_UNORM: case PIPE_FORMAT_X8Z24_UNORM: - debug_printf("r300: Note: Got unsupported format: %s in %s\n", - pf_name(format), __FUNCTION__); + SCREEN_DBG(r300_screen(screen), DBG_TEX, + "r300: Note: Got unsupported format: %s in %s\n", + pf_name(format), __FUNCTION__); return FALSE; - /* XXX These don't even exist - case PIPE_FORMAT_A32R32G32B32: - case PIPE_FORMAT_A16R16G16B16: */ - /* XXX What the deuce is UV88? (r3xx accel page 14) - debug_printf("r300: Warning: Got unimplemented format: %s in %s\n", - pf_name(format), __FUNCTION__); - return FALSE; */ - - /* XXX Supported yet unimplemented r5xx formats: */ - /* XXX Again, what is UV1010 this time? (r5xx accel page 148) */ - /* XXX Even more that don't exist - case PIPE_FORMAT_A10R10G10B10_UNORM: - case PIPE_FORMAT_A2R10G10B10_UNORM: - case PIPE_FORMAT_I10_UNORM: - debug_printf( - "r300: Warning: Got unimplemented r500 format: %s in %s\n", - pf_name(format), __FUNCTION__); - return FALSE; */ + /* XXX Add all remaining gallium-supported formats, + * see util/u_format.csv. */ default: /* Unknown format... */ @@ -286,30 +298,6 @@ static boolean check_tex_format(enum pipe_format format, uint32_t usage, return (retval >= usage); } -static boolean r300_is_format_supported(struct pipe_screen* pscreen, - enum pipe_format format, - enum pipe_texture_target target, - unsigned tex_usage, - unsigned geom_flags) -{ - switch (target) { - case PIPE_TEXTURE_1D: /* handle 1D textures as 2D ones */ - case PIPE_TEXTURE_2D: - case PIPE_TEXTURE_3D: - case PIPE_TEXTURE_CUBE: - return check_tex_format(format, tex_usage, - r300_screen(pscreen)->caps->is_r500); - - default: - debug_printf("r300: Fatal: This is not a format target: %d\n", - target); - assert(0); - break; - } - - return FALSE; -} - static struct pipe_transfer* r300_get_tex_transfer(struct pipe_screen *screen, struct pipe_texture *texture, @@ -319,6 +307,7 @@ r300_get_tex_transfer(struct pipe_screen *screen, { struct r300_texture *tex = (struct r300_texture *)texture; struct r300_transfer *trans; + struct r300_screen *rscreen = r300_screen(screen); unsigned offset; offset = r300_texture_get_offset(tex, level, zslice, face); /* in bytes */ @@ -330,11 +319,8 @@ r300_get_tex_transfer(struct pipe_screen *screen, trans->transfer.y = y; trans->transfer.width = w; trans->transfer.height = h; - trans->transfer.stride = r300_texture_get_stride(tex, level); + trans->transfer.stride = r300_texture_get_stride(rscreen, tex, level); trans->transfer.usage = usage; - - /* XXX not sure whether it's required to set these two, - the driver doesn't use them */ trans->transfer.zslice = zslice; trans->transfer.face = face; @@ -396,6 +382,7 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) caps->num_frag_pipes = radeon_winsys->gb_pipes; caps->num_z_pipes = radeon_winsys->z_pipes; + r300_init_debug(r300screen); r300_parse_chipset(caps); r300screen->caps = caps; diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 2217988add..580fda3984 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -35,6 +35,9 @@ struct r300_screen { /* Chipset capabilities */ struct r300_capabilities* caps; + + /** Combination of DBG_xxx flags */ + unsigned debug; }; struct r300_transfer { @@ -60,4 +63,44 @@ r300_transfer(struct pipe_transfer* transfer) /* Creates a new r300 screen. */ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); +/* Debug functionality. */ + +/** + * Debug flags to disable/enable certain groups of debugging outputs. + * + * \note These may be rather coarse, and the grouping may be impractical. + * If you find, while debugging the driver, that a different grouping + * of these flags would be beneficial, just feel free to change them + * but make sure to update the documentation in r300_debug.c to reflect + * 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 +/*@}*/ + +static INLINE boolean SCREEN_DBG_ON(struct r300_screen * screen, unsigned flags) +{ + return (screen->debug & flags) ? TRUE : FALSE; +} + +static INLINE void SCREEN_DBG(struct r300_screen * screen, unsigned flags, + const char * fmt, ...) +{ + if (SCREEN_DBG_ON(screen, flags)) { + va_list va; + va_start(va, fmt); + debug_vprintf(fmt, va); + va_end(va); + } +} + +void r300_init_debug(struct r300_screen* ctx); + #endif /* R300_SCREEN_H */ + diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 60ad763cf4..a5c0869066 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -30,7 +30,6 @@ #include "tgsi/tgsi_parse.h" #include "pipe/p_config.h" -#include "pipe/internal/p_winsys_screen.h" #include "r300_context.h" #include "r300_reg.h" @@ -162,17 +161,18 @@ static boolean blend_discard_if_src_alpha_color_1(unsigned srcRGB, unsigned srcA static void* r300_create_blend_state(struct pipe_context* pipe, const struct pipe_blend_state* state) { + struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state); - if (state->blend_enable) + if (state->rt[0].blend_enable) { - unsigned eqRGB = state->rgb_func; - unsigned srcRGB = state->rgb_src_factor; - unsigned dstRGB = state->rgb_dst_factor; + unsigned eqRGB = state->rt[0].rgb_func; + unsigned srcRGB = state->rt[0].rgb_src_factor; + unsigned dstRGB = state->rt[0].rgb_dst_factor; - unsigned eqA = state->alpha_func; - unsigned srcA = state->alpha_src_factor; - unsigned dstA = state->alpha_dst_factor; + unsigned eqA = state->rt[0].alpha_func; + unsigned srcA = state->rt[0].alpha_src_factor; + unsigned dstA = state->rt[0].alpha_dst_factor; /* despite the name, ALPHA_BLEND_ENABLE has nothing to do with alpha, * this is just the crappy D3D naming */ @@ -289,18 +289,18 @@ static void* r300_create_blend_state(struct pipe_context* pipe, (state->logicop_func) << R300_RB3D_ROPCNTL_ROP_SHIFT; } - /* Color Channel Mask */ - if (state->colormask & PIPE_MASK_R) { - blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_RED_MASK0; - } - if (state->colormask & PIPE_MASK_G) { - blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_GREEN_MASK0; - } - if (state->colormask & PIPE_MASK_B) { - blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_BLUE_MASK0; - } - if (state->colormask & PIPE_MASK_A) { - blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK0; + /* Color channel masks for all MRTs. */ + blend->color_channel_mask = state->rt[0].colormask; + if (r300screen->caps->is_r500 && state->independent_blend_enable) { + if (state->rt[1].blend_enable) { + blend->color_channel_mask |= (state->rt[1].colormask << 4); + } + if (state->rt[2].blend_enable) { + blend->color_channel_mask |= (state->rt[2].colormask << 8); + } + if (state->rt[3].blend_enable) { + blend->color_channel_mask |= (state->rt[3].colormask << 12); + } } if (state->dither) { @@ -486,19 +486,47 @@ static void const struct pipe_framebuffer_state* state) { struct r300_context* r300 = r300_context(pipe); + uint32_t zbuffer_bpp = 0; + + r300->fb_state.size = (10 * state->nr_cbufs) + + (2 * (4 - state->nr_cbufs)) + + (state->zsbuf ? 10 : 0) + 6; + + if (state->nr_cbufs > 4) { + debug_printf("r300: Implementation error: Too many MRTs in %s, " + "refusing to bind framebuffer state!\n", __FUNCTION__); + return; + } if (r300->draw) { draw_flush(r300->draw); } - r300->framebuffer_state = *state; + r300->fb_state.state = state; /* Don't rely on the order of states being set for the first time. */ - r300->dirty_state |= R300_NEW_FRAMEBUFFERS; - + /* XXX wait what */ r300->blend_state.dirty = TRUE; r300->dsa_state.dirty = TRUE; + r300->fb_state.dirty = TRUE; r300->scissor_state.dirty = TRUE; + + /* Polygon offset depends on the zbuffer bit depth. */ + if (state->zsbuf && r300->polygon_offset_enabled) { + switch (util_format_get_blocksize(state->zsbuf->texture->format)) { + case 2: + zbuffer_bpp = 16; + break; + case 4: + zbuffer_bpp = 24; + break; + } + + if (r300->zbuffer_bpp != zbuffer_bpp) { + r300->zbuffer_bpp = zbuffer_bpp; + r300->rs_state.dirty = TRUE; + } + } } /* Create fragment shader state. */ @@ -534,7 +562,7 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) r300_pick_fragment_shader(r300); if (r300->vs && r300_vertex_shader_setup_wpos(r300)) { - r300->dirty_state |= R300_NEW_VERTEX_FORMAT; + r300->vertex_format_state.dirty = TRUE; } r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS; @@ -602,9 +630,6 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->line_control = pack_float_16_6x(state->line_width) | R300_GA_LINE_CNTL_END_TYPE_COMP; - /* XXX I think there is something wrong with the polygon mode, - * XXX re-test when r300g is in a better shape */ - /* Enable polygon mode */ if (state->fill_cw != PIPE_POLYGON_MODE_FILL || state->fill_ccw != PIPE_POLYGON_MODE_FILL) { @@ -657,10 +682,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe, } if (rs->polygon_offset_enable) { - rs->depth_offset_front = rs->depth_offset_back = - fui(state->offset_units); - rs->depth_scale_front = rs->depth_scale_back = - fui(state->offset_scale); + rs->depth_offset = state->offset_units; + rs->depth_scale = state->offset_scale; } if (state->line_stipple_enable) { @@ -694,8 +717,10 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) if (rs) { r300->tcl_bypass = rs->rs.bypass_vs_clip_and_viewport; + r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; } else { r300->tcl_bypass = FALSE; + r300->polygon_offset_enabled = FALSE; } r300->rs_state.state = rs; @@ -705,7 +730,6 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) r300->viewport_state.dirty = TRUE; /* XXX Clean these up when we move to atom emits */ - r300->dirty_state |= R300_NEW_RS_BLOCK; if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) { r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; } @@ -906,7 +930,23 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, draw_set_vertex_buffers(r300->draw, count, buffers); } - r300->dirty_state |= R300_NEW_VERTEX_FORMAT; + r300->vertex_format_state.dirty = TRUE; +} + +static boolean r300_validate_aos(struct r300_context *r300) +{ + struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; + struct pipe_vertex_element *velem = r300->vertex_element; + int i; + + /* Check if formats and strides are aligned to the size of DWORD. */ + for (i = 0; i < r300->vertex_element_count; i++) { + if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 || + util_format_get_blocksize(velem[i].src_format) % 4 != 0) { + return FALSE; + } + } + return TRUE; } static void r300_set_vertex_elements(struct pipe_context* pipe, @@ -924,6 +964,12 @@ static void r300_set_vertex_elements(struct pipe_context* pipe, draw_flush(r300->draw); draw_set_vertex_elements(r300->draw, count, elements); } + + if (!r300_validate_aos(r300)) { + /* XXX We should fallback using draw. */ + assert(0); + abort(); + } } static void* r300_create_vs_state(struct pipe_context* pipe, @@ -964,9 +1010,10 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) r300_vertex_shader_setup_wpos(r300); } + r300->vertex_format_state.dirty = TRUE; + r300->dirty_state |= - R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS | - R300_NEW_VERTEX_FORMAT; + R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS; } else { draw_flush(r300->draw); draw_bind_vertex_shader(r300->draw, diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 192846411b..bad9e76067 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -37,32 +37,6 @@ /* r300_state_derived: Various bits of state which are dependent upon * currently bound CSO data. */ -struct r300_shader_key { - struct r300_vertex_shader* vs; - struct r300_fragment_shader* fs; -}; - -struct r300_shader_derived_value { - struct r300_vertex_format* vformat; - struct r300_rs_block* rs_block; -}; - -unsigned r300_shader_key_hash(void* key) { - struct r300_shader_key* shader_key = (struct r300_shader_key*)key; - unsigned vs = (intptr_t)shader_key->vs; - unsigned fs = (intptr_t)shader_key->fs; - - return (vs << 16) | (fs & 0xffff); -} - -int r300_shader_key_compare(void* key1, void* key2) { - struct r300_shader_key* shader_key1 = (struct r300_shader_key*)key1; - struct r300_shader_key* shader_key2 = (struct r300_shader_key*)key2; - - return (shader_key1->vs == shader_key2->vs) && - (shader_key1->fs == shader_key2->fs); -} - static void r300_draw_emit_attrib(struct r300_context* r300, enum attrib_emit emit, enum interp_mode interp, @@ -74,7 +48,9 @@ static void r300_draw_emit_attrib(struct r300_context* r300, output = draw_find_shader_output(r300->draw, info->output_semantic_name[index], info->output_semantic_index[index]); - draw_emit_vertex_attr(&r300->vertex_info->vinfo, emit, interp, output); + draw_emit_vertex_attr( + (struct vertex_info*)r300->vertex_format_state.state, + emit, interp, output); } static void r300_draw_emit_all_attribs(struct r300_context* r300) @@ -130,7 +106,8 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300) /* Update the PSC tables. */ static void r300_vertex_psc(struct r300_context* r300) { - struct r300_vertex_info *vformat = r300->vertex_info; + struct r300_vertex_info *vformat = + (struct r300_vertex_info*)r300->vertex_format_state.state; uint16_t type, swizzle; enum pipe_format format; unsigned i; @@ -182,7 +159,8 @@ static void r300_vertex_psc(struct r300_context* r300) /* Update the PSC tables for SW TCL, using Draw. */ static void r300_swtcl_vertex_psc(struct r300_context* r300) { - struct r300_vertex_info *vformat = r300->vertex_info; + struct r300_vertex_info *vformat = + (struct r300_vertex_info*)r300->vertex_format_state.state; struct vertex_info* vinfo = &vformat->vinfo; uint16_t type, swizzle; enum pipe_format format; @@ -327,7 +305,7 @@ static void r300_update_rs_block(struct r300_context* r300, struct r300_shader_semantics* vs_outputs, struct r300_shader_semantics* fs_inputs) { - struct r300_rs_block* rs = r300->rs_block; + struct r300_rs_block rs = { { 0 } }; int i, col_count = 0, tex_count = 0, fp_offset = 0; void (*rX00_rs_col)(struct r300_rs_block*, int, int, boolean); void (*rX00_rs_col_write)(struct r300_rs_block*, int, int); @@ -350,14 +328,15 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize colors. */ for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) { + if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || + vs_outputs->color[1] != ATTR_UNUSED) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ - rX00_rs_col(rs, col_count, i, FALSE); + rX00_rs_col(&rs, col_count, i, FALSE); /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->color[i] != ATTR_UNUSED) { - rX00_rs_col_write(rs, col_count, fp_offset); + rX00_rs_col_write(&rs, col_count, fp_offset); fp_offset++; } col_count++; @@ -375,11 +354,11 @@ static void r300_update_rs_block(struct r300_context* r300, if (vs_outputs->generic[i] != ATTR_UNUSED) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ - rX00_rs_tex(rs, tex_count, tex_count, FALSE); + rX00_rs_tex(&rs, tex_count, tex_count, FALSE); /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->generic[i] != ATTR_UNUSED) { - rX00_rs_tex_write(rs, tex_count, fp_offset); + rX00_rs_tex_write(&rs, tex_count, fp_offset); fp_offset++; } tex_count++; @@ -396,11 +375,11 @@ static void r300_update_rs_block(struct r300_context* r300, if (vs_outputs->fog != ATTR_UNUSED) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ - rX00_rs_tex(rs, tex_count, tex_count, TRUE); + rX00_rs_tex(&rs, tex_count, tex_count, TRUE); /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->fog != ATTR_UNUSED) { - rX00_rs_tex_write(rs, tex_count, fp_offset); + rX00_rs_tex_write(&rs, tex_count, fp_offset); fp_offset++; } tex_count++; @@ -415,8 +394,8 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize WPOS. */ /* If the FS doesn't need it, it's not written by the VS. */ if (fs_inputs->wpos != ATTR_UNUSED) { - rX00_rs_tex(rs, tex_count, tex_count, FALSE); - rX00_rs_tex_write(rs, tex_count, fp_offset); + rX00_rs_tex(&rs, tex_count, tex_count, FALSE); + rX00_rs_tex_write(&rs, tex_count, fp_offset); fp_offset++; tex_count++; @@ -424,51 +403,33 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize at least one color, or bad things happen. */ if (col_count == 0 && tex_count == 0) { - rX00_rs_col(rs, 0, 0, TRUE); + rX00_rs_col(&rs, 0, 0, TRUE); col_count++; } - rs->count = (tex_count*4) | (col_count << R300_IC_COUNT_SHIFT) | + rs.count = (tex_count*4) | (col_count << R300_IC_COUNT_SHIFT) | R300_HIRES_EN; - rs->inst_count = MAX3(col_count - 1, tex_count - 1, 0); + rs.inst_count = MAX3(col_count - 1, tex_count - 1, 0); + + /* Now, after all that, see if we actually need to update the state. */ + if (memcmp(r300->rs_block_state.state, &rs, sizeof(struct r300_rs_block))) { + memcpy(r300->rs_block_state.state, &rs, sizeof(struct r300_rs_block)); + r300->rs_block_state.dirty = TRUE; + } } -/* Update the vertex format. */ +/* Update the shader-dependant states. */ static void r300_update_derived_shader_state(struct r300_context* r300) { struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct r300_vertex_info *vformat = + (struct r300_vertex_info*)r300->vertex_format_state.state; + struct vertex_info* vinfo = &vformat->vinfo; - /* - struct r300_shader_key* key; - struct r300_shader_derived_value* value; - key = CALLOC_STRUCT(r300_shader_key); - key->vs = r300->vs; - key->fs = r300->fs; - - value = (struct r300_shader_derived_value*) - util_hash_table_get(r300->shader_hash_table, (void*)key); - if (value) { - //vformat = value->vformat; - rs_block = value->rs_block; - - FREE(key); - } else { - rs_block = CALLOC_STRUCT(r300_rs_block); - value = CALLOC_STRUCT(r300_shader_derived_value); - - r300_update_rs_block(r300, rs_block); - - //value->vformat = vformat; - value->rs_block = rs_block; - util_hash_table_set(r300->shader_hash_table, - (void*)key, (void*)value); - } */ - - /* Reset structures */ - memset(r300->rs_block, 0, sizeof(struct r300_rs_block)); - memset(r300->vertex_info, 0, sizeof(struct r300_vertex_info)); - memcpy(r300->vertex_info->vinfo.hwfmt, r300->vs->hwfmt, sizeof(uint)*4); + /* Mmm, delicious hax */ + memset(r300->vertex_format_state.state, 0, sizeof(struct r300_vertex_info)); + memcpy(vinfo->hwfmt, r300->vs->hwfmt, sizeof(uint)*4); r300_update_rs_block(r300, &r300->vs->outputs, &r300->fs->inputs); @@ -476,11 +437,10 @@ static void r300_update_derived_shader_state(struct r300_context* r300) r300_vertex_psc(r300); } else { r300_draw_emit_all_attribs(r300); - draw_compute_vertex_size(&r300->vertex_info->vinfo); + draw_compute_vertex_size( + (struct vertex_info*)r300->vertex_format_state.state); r300_swtcl_vertex_psc(r300); } - - r300->dirty_state |= R300_NEW_RS_BLOCK; } static boolean r300_dsa_writes_depth_stencil(struct r300_dsa_state* dsa) @@ -558,8 +518,8 @@ void r300_update_derived_state(struct r300_context* r300) { /* XXX */ if (r300->dirty_state & - (R300_NEW_FRAGMENT_SHADER | R300_NEW_VERTEX_SHADER | - R300_NEW_VERTEX_FORMAT) || r300->rs_state.dirty) { + (R300_NEW_FRAGMENT_SHADER | R300_NEW_VERTEX_SHADER) || + r300->vertex_format_state.dirty || r300->rs_state.dirty) { r300_update_derived_shader_state(r300); } diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 35be00e1b0..5df6815221 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -81,9 +81,6 @@ static INLINE uint32_t r300_translate_blend_factor(int blend_fact) return R300_BLEND_GL_CONST_COLOR; case PIPE_BLENDFACTOR_CONST_ALPHA: return R300_BLEND_GL_CONST_ALPHA; - /* XXX WTF are these? - case PIPE_BLENDFACTOR_SRC1_COLOR: - case PIPE_BLENDFACTOR_SRC1_ALPHA: */ case PIPE_BLENDFACTOR_ZERO: return R300_BLEND_GL_ZERO; case PIPE_BLENDFACTOR_INV_SRC_COLOR: @@ -98,9 +95,16 @@ static INLINE uint32_t r300_translate_blend_factor(int blend_fact) return R300_BLEND_GL_ONE_MINUS_CONST_COLOR; case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return R300_BLEND_GL_ONE_MINUS_CONST_ALPHA; - /* XXX see above + + case PIPE_BLENDFACTOR_SRC1_COLOR: + case PIPE_BLENDFACTOR_SRC1_ALPHA: case PIPE_BLENDFACTOR_INV_SRC1_COLOR: - case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: */ + case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: + debug_printf("r300: Implementation error: " + "Bad blend factor %d not supported!\n", blend_fact); + assert(0); + break; + default: debug_printf("r300: Unknown blend factor %d\n", blend_fact); assert(0); @@ -331,7 +335,10 @@ static INLINE uint32_t r300_translate_colorformat(enum pipe_format format) { switch (format) { /* 8-bit buffers */ + case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_I8_UNORM: + case PIPE_FORMAT_L8_UNORM: + /* case PIPE_FORMAT_S8_UNORM: ??? */ return R300_COLOR_FORMAT_I8; /* 16-bit buffers */ case PIPE_FORMAT_R5G6B5_UNORM: @@ -408,6 +415,16 @@ static INLINE uint32_t r300_translate_out_fmt(enum pipe_format format) return R300_US_OUT_FMT_C4_8 | R300_C0_SEL_A | R300_C1_SEL_B | R300_C2_SEL_G | R300_C3_SEL_R; + + /* 8-bit outputs */ + case PIPE_FORMAT_A8_UNORM: + return R300_US_OUT_FMT_C4_8 | + R300_C0_SEL_A; + case PIPE_FORMAT_I8_UNORM: + case PIPE_FORMAT_L8_UNORM: + return R300_US_OUT_FMT_C4_8 | + R300_C0_SEL_R; + /* R300_OUT_SIGN(x) */ default: debug_printf("r300: Implementation error: " "Got unsupported output format %s in %s\n", @@ -537,6 +554,7 @@ r300_translate_vertex_data_type(enum pipe_format format) { static INLINE uint16_t r300_translate_vertex_data_swizzle(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); + unsigned swizzle[4], i; assert(format); @@ -547,11 +565,26 @@ r300_translate_vertex_data_swizzle(enum pipe_format format) { return 0; } - return ((desc->swizzle[0] << R300_SWIZZLE_SELECT_X_SHIFT) | - (desc->swizzle[1] << R300_SWIZZLE_SELECT_Y_SHIFT) | - (desc->swizzle[2] << R300_SWIZZLE_SELECT_Z_SHIFT) | - (desc->swizzle[3] << R300_SWIZZLE_SELECT_W_SHIFT) | - (0xf << R300_WRITE_ENA_SHIFT)); + /* Swizzles for 8bits formats are in the reversed order, not sure why. */ + if (desc->channel[0].size == 8) { + for (i = 0; i < 4; i++) { + if (desc->swizzle[i] <= 3) { + swizzle[i] = 3 - desc->swizzle[i]; + } else { + swizzle[i] = desc->swizzle[i]; + } + } + } else { + for (i = 0; i < 4; i++) { + swizzle[i] = desc->swizzle[i]; + } + } + + return ((swizzle[0] << R300_SWIZZLE_SELECT_X_SHIFT) | + (swizzle[1] << R300_SWIZZLE_SELECT_Y_SHIFT) | + (swizzle[2] << R300_SWIZZLE_SELECT_Z_SHIFT) | + (swizzle[3] << R300_SWIZZLE_SELECT_W_SHIFT) | + (0xf << R300_WRITE_ENA_SHIFT)); } #endif /* R300_STATE_INLINES_H */ diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index b0f309695c..97927acf1b 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -38,12 +38,12 @@ struct pipe_viewport_state r300_viewport_identity = { * * Note that eventually this should be empty, but it's useful for development * and general unduplication of code. */ -void r300_emit_invariant_state(struct r300_context* r300) +void r300_emit_invariant_state(struct r300_context* r300, void* state) { struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); - BEGIN_CS(16 + (caps->has_tcl ? 2: 0)); + BEGIN_CS(14 + (caps->has_tcl ? 2: 0)); /*** Graphics Backend (GB) ***/ /* Various GB enables */ @@ -58,8 +58,6 @@ void r300_emit_invariant_state(struct r300_context* r300) */ /* Source of fog depth */ OUT_CS_REG(R300_GB_SELECT, R300_GB_FOG_SELECT_1_1_W); - /* AA enable */ - OUT_CS_REG(R300_GB_AA_CONFIG, 0x0); /*** Fog (FG) ***/ OUT_CS_REG(R300_FG_FOG_BLEND, 0x0); @@ -79,7 +77,8 @@ void r300_emit_invariant_state(struct r300_context* r300) END_CS; /* XXX unsorted stuff from surface_fill */ - BEGIN_CS(44 + (caps->has_tcl ? 7 : 0) + (caps->is_r500 ? 4 : 0)); + BEGIN_CS(44 + (caps->has_tcl ? 7 : 0) + + (caps->family >= CHIP_FAMILY_RV350 ? 4 : 0)); if (caps->has_tcl) { /*Flushing PVS is required before the VAP_GB registers can be changed*/ diff --git a/src/gallium/drivers/r300/r300_state_invariant.h b/src/gallium/drivers/r300/r300_state_invariant.h index 05cff0d6df..5d1a963654 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.h +++ b/src/gallium/drivers/r300/r300_state_invariant.h @@ -25,6 +25,6 @@ struct r300_context; -void r300_emit_invariant_state(struct r300_context* r300); +void r300_emit_invariant_state(struct r300_context* r300, void* state); #endif /* R300_STATE_INVARIANT_H */ diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index a9bbdd56d8..67bf8ce13f 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -30,6 +30,8 @@ #include "r300_texture.h" #include "r300_screen.h" +#include "radeon_winsys.h" + #define TILE_WIDTH 0 #define TILE_HEIGHT 1 @@ -42,10 +44,11 @@ static const unsigned microblock_table[5][3][2] = { {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ }; -static void r300_setup_texture_state(struct r300_texture* tex, boolean is_r500) +static void r300_setup_texture_state(struct r300_screen* screen, struct r300_texture* tex) { struct r300_texture_state* state = &tex->state; struct pipe_texture *pt = &tex->tex; + boolean is_r500 = screen->caps->is_r500; state->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); @@ -79,8 +82,8 @@ static void r300_setup_texture_state(struct r300_texture* tex, boolean is_r500) } assert(is_r500 || (pt->width0 <= 2048 && pt->height0 <= 2048)); - debug_printf("r300: Set texture state (%dx%d, %d levels)\n", - pt->width0, pt->height0, pt->last_level); + SCREEN_DBG(screen, DBG_TEX, "r300: Set texture state (%dx%d, %d levels)\n", + pt->width0, pt->height0, pt->last_level); } unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, @@ -123,7 +126,8 @@ static unsigned r300_texture_get_tile_size(struct r300_texture* tex, int dim) * Return the stride, in bytes, of the texture images of the given texture * at the given level. */ -unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level) +unsigned r300_texture_get_stride(struct r300_screen* screen, + struct r300_texture* tex, unsigned level) { unsigned tile_width, width; @@ -132,16 +136,20 @@ unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level) /* Check the level. */ if (level > tex->tex.last_level) { - debug_printf("%s: level (%u) > last_level (%u)\n", __FUNCTION__, - level, tex->tex.last_level); + SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", + __FUNCTION__, level, tex->tex.last_level); return 0; } - tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH); - width = align(u_minify(tex->tex.width0, level), tile_width); + width = u_minify(tex->tex.width0, level); - /* Should already be aligned except for S3TC. */ - return align(util_format_get_stride(tex->tex.format, width), 32); + if (!util_format_is_compressed(tex->tex.format)) { + tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH); + width = align(width, tile_width); + return util_format_get_stride(tex->tex.format, width); + } else { + return align(util_format_get_stride(tex->tex.format, width), 32); + } } static unsigned r300_texture_get_nblocksy(struct r300_texture* tex, @@ -149,21 +157,27 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture* tex, { unsigned height, tile_height; - tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT); - height = align(u_minify(tex->tex.height0, level), tile_height); + height = u_minify(tex->tex.height0, level); + + if (!util_format_is_compressed(tex->tex.format)) { + tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT); + height = align(height, tile_height); + } return util_format_get_nblocksy(tex->tex.format, height); } -static void r300_setup_miptree(struct r300_texture* tex) +static void r300_setup_miptree(struct r300_screen* screen, + struct r300_texture* tex) { struct pipe_texture* base = &tex->tex; unsigned stride, size, layer_size, nblocksy, i; - debug_printf("r300: Making miptree for texture, format %s\n", pf_name(base->format)); + SCREEN_DBG(screen, DBG_TEX, "r300: Making miptree for texture, format %s\n", + pf_name(base->format)); for (i = 0; i <= base->last_level; i++) { - stride = r300_texture_get_stride(tex, i); + stride = r300_texture_get_stride(screen, tex, i); nblocksy = r300_texture_get_nblocksy(tex, i); layer_size = stride * nblocksy; @@ -177,7 +191,7 @@ static void r300_setup_miptree(struct r300_texture* tex) tex->layer_size[i] = layer_size; tex->pitch[i] = stride / util_format_get_blocksize(base->format); - debug_printf("r300: Texture miptree: Level %d " + SCREEN_DBG(screen, DBG_TEX, "r300: Texture miptree: Level %d " "(%dx%dx%d px, pitch %d bytes) %d bytes total\n", i, u_minify(base->width0, i), u_minify(base->height0, i), u_minify(base->depth0, i), stride, tex->size); @@ -196,6 +210,8 @@ static struct pipe_texture* const struct pipe_texture* template) { struct r300_texture* tex = CALLOC_STRUCT(r300_texture); + struct r300_screen* rscreen = r300_screen(screen); + struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; if (!tex) { return NULL; @@ -206,12 +222,16 @@ static struct pipe_texture* tex->tex.screen = screen; r300_setup_flags(tex); - r300_setup_miptree(tex); - r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500); + r300_setup_miptree(rscreen, tex); + r300_setup_texture_state(rscreen, tex); tex->buffer = screen->buffer_create(screen, 2048, PIPE_BUFFER_USAGE_PIXEL, tex->size); + winsys->buffer_set_tiling(winsys, tex->buffer, + tex->pitch[0], + tex->microtile != R300_BUFFER_LINEAR, + tex->macrotile != R300_BUFFER_LINEAR); if (!tex->buffer) { FREE(tex); @@ -273,6 +293,7 @@ static struct pipe_texture* struct pipe_buffer* buffer) { struct r300_texture* tex; + struct r300_screen* rscreen = r300_screen(screen); /* Support only 2D textures without mipmaps */ if (base->target != PIPE_TEXTURE_2D || @@ -294,7 +315,7 @@ static struct pipe_texture* tex->pitch[0] = *stride / util_format_get_blocksize(base->format); r300_setup_flags(tex); - r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500); + r300_setup_texture_state(rscreen, tex); pipe_buffer_reference(&tex->buffer, buffer); @@ -361,7 +382,8 @@ void r300_init_screen_texture_functions(struct pipe_screen* screen) screen->video_surface_destroy= r300_video_surface_destroy; } -boolean r300_get_texture_buffer(struct pipe_texture* texture, +boolean r300_get_texture_buffer(struct pipe_screen* screen, + struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride) { @@ -373,7 +395,7 @@ boolean r300_get_texture_buffer(struct pipe_texture* texture, pipe_buffer_reference(buffer, tex->buffer); if (stride) { - *stride = r300_texture_get_stride(tex, 0); + *stride = r300_texture_get_stride(r300_screen(screen), tex, 0); } return TRUE; diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 55ceb1a513..453fb1accc 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -31,7 +31,8 @@ struct r300_texture; void r300_init_screen_texture_functions(struct pipe_screen* screen); -unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level); +unsigned r300_texture_get_stride(struct r300_screen* screen, + struct r300_texture* tex, unsigned level); unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, unsigned zslice, unsigned face); @@ -41,6 +42,7 @@ static INLINE uint32_t r300_translate_texformat(enum pipe_format format) { switch (format) { /* X8 */ + case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_I8_UNORM: return R300_EASY_TX_FORMAT(X, X, X, X, X8); case PIPE_FORMAT_L8_UNORM: @@ -115,7 +117,8 @@ r300_video_surface(struct pipe_video_surface *pvs) #ifndef R300_WINSYS_H -boolean r300_get_texture_buffer(struct pipe_texture* texture, +boolean r300_get_texture_buffer(struct pipe_screen* screen, + struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride); diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 68aef70872..9fbb830047 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -124,7 +124,8 @@ static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs) /* Colors. */ for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) { + if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || + vs_outputs->color[1] != ATTR_UNUSED) { hwfmt[1] |= R300_INPUT_CNTL_COLOR; hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i; } @@ -182,7 +183,8 @@ static void r300_stream_locations_notcl( /* Colors. */ for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) { + if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || + vs_outputs->color[1] != ATTR_UNUSED) { stream_loc[tabi++] = 2 + i; } } @@ -259,7 +261,8 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) for (i = 0; i < ATTR_COLOR_COUNT; i++) { if (outputs->color[i] != ATTR_UNUSED) { c->code->outputs[outputs->color[i]] = reg++; - } else if (any_bcolor_used) { + } else if (any_bcolor_used || + outputs->color[1] != ATTR_UNUSED) { reg++; } } diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 1ae6de70fe..bdb8b54bab 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -40,7 +40,8 @@ extern "C" { struct pipe_context* r300_create_context(struct pipe_screen* screen, struct radeon_winsys* radeon_winsys); -boolean r300_get_texture_buffer(struct pipe_texture* texture, +boolean r300_get_texture_buffer(struct pipe_screen* screen, + struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride); diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile index bcb887a0b2..e4ac49fa85 100644 --- a/src/gallium/drivers/softpipe/Makefile +++ b/src/gallium/drivers/softpipe/Makefile @@ -32,6 +32,7 @@ C_SOURCES = \ sp_tex_tile_cache.c \ sp_tile_cache.c \ sp_surface.c \ - sp_video_context.c + sp_video_context.c \ + sp_winsys.c include ../../Makefile.template diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index aac9edf44e..3042e556c6 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -34,6 +34,7 @@ softpipe = env.ConvenienceLibrary( 'sp_texture.c', 'sp_tile_cache.c', 'sp_video_context.c', + 'sp_winsys.c' ]) Export('softpipe') diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index 8e01793940..53133d2888 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -43,7 +43,6 @@ #include "sp_surface.h" #include "sp_tile_cache.h" #include "sp_tex_tile_cache.h" -#include "sp_texture.h" #include "sp_winsys.h" #include "sp_query.h" @@ -112,9 +111,13 @@ softpipe_destroy( struct pipe_context *pipe ) pipe_texture_reference(&softpipe->vertex_textures[i], NULL); } - for (i = 0; i < Elements(softpipe->constants); i++) { - if (softpipe->constants[i]) { - pipe_buffer_reference(&softpipe->constants[i], NULL); + for (i = 0; i < PIPE_SHADER_TYPES; i++) { + uint j; + + for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { + if (softpipe->constants[i][j]) { + pipe_buffer_reference(&softpipe->constants[i][j], NULL); + } } } diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index da673c57ad..be4613b622 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -63,7 +63,7 @@ struct softpipe_context { /** Other rendering state */ struct pipe_blend_color blend_color; struct pipe_clip_state clip; - struct pipe_buffer *constants[PIPE_SHADER_TYPES]; + struct pipe_buffer *constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; @@ -92,7 +92,7 @@ struct softpipe_context { ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS]; /** Mapped constant buffers */ - void *mapped_constants[PIPE_SHADER_TYPES]; + void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; /** Vertex format */ struct vertex_info vertex_info; diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index 03b58d2fb7..2b82427d54 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -49,30 +49,36 @@ static void softpipe_map_constant_buffers(struct softpipe_context *sp) { struct pipe_winsys *ws = sp->pipe.winsys; - uint i, vssize, gssize; + uint i; for (i = 0; i < PIPE_SHADER_TYPES; i++) { - if (sp->constants[i] && sp->constants[i]->size) - sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i], - PIPE_BUFFER_USAGE_CPU_READ); + uint j; + + for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { + if (sp->constants[i][j] && sp->constants[i][j]->size) { + sp->mapped_constants[i][j] = ws->buffer_map(ws, + sp->constants[i][j], + PIPE_BUFFER_USAGE_CPU_READ); + } + } } - if (sp->constants[PIPE_SHADER_VERTEX]) - vssize = sp->constants[PIPE_SHADER_VERTEX]->size; - else - vssize = 0; - - if (sp->constants[PIPE_SHADER_GEOMETRY]) - gssize = sp->constants[PIPE_SHADER_GEOMETRY]->size; - else - gssize = 0; - - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX, - sp->mapped_constants[PIPE_SHADER_VERTEX], - vssize); - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_GEOMETRY, - sp->mapped_constants[PIPE_SHADER_GEOMETRY], - gssize); + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + if (sp->constants[PIPE_SHADER_VERTEX][i]) { + draw_set_mapped_constant_buffer(sp->draw, + PIPE_SHADER_VERTEX, + i, + sp->mapped_constants[PIPE_SHADER_VERTEX][i], + sp->constants[PIPE_SHADER_VERTEX][i]->size); + } + if (sp->constants[PIPE_SHADER_GEOMETRY][i]) { + draw_set_mapped_constant_buffer(sp->draw, + PIPE_SHADER_GEOMETRY, + i, + sp->mapped_constants[PIPE_SHADER_GEOMETRY][i], + sp->constants[PIPE_SHADER_GEOMETRY][i]->size); + } + } } @@ -87,13 +93,28 @@ softpipe_unmap_constant_buffers(struct softpipe_context *sp) */ draw_flush(sp->draw); - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX, NULL, 0); - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_GEOMETRY, NULL, 0); + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + draw_set_mapped_constant_buffer(sp->draw, + PIPE_SHADER_VERTEX, + i, + NULL, + 0); + draw_set_mapped_constant_buffer(sp->draw, + PIPE_SHADER_GEOMETRY, + i, + NULL, + 0); + } for (i = 0; i < PIPE_SHADER_TYPES; i++) { - if (sp->constants[i] && sp->constants[i]->size) - ws->buffer_unmap(ws, sp->constants[i]); - sp->mapped_constants[i] = NULL; + uint j; + + for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { + if (sp->constants[i][j] && sp->constants[i][j]->size) { + ws->buffer_unmap(ws, sp->constants[i][j]); + } + sp->mapped_constants[i][j] = NULL; + } } } diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c index 75dac810a1..e8952bf4fb 100644 --- a/src/gallium/drivers/softpipe/sp_flush.c +++ b/src/gallium/drivers/softpipe/sp_flush.c @@ -34,11 +34,9 @@ #include "draw/draw_context.h" #include "sp_flush.h" #include "sp_context.h" -#include "sp_surface.h" #include "sp_state.h" #include "sp_tile_cache.h" #include "sp_tex_tile_cache.h" -#include "sp_winsys.h" void diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index f912950658..acee213670 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -135,7 +135,7 @@ fs_sse_run( const struct sp_fragment_shader *base, tgsi_set_exec_mask(machine, 1, 1, 1, 1); shader->func( machine, - machine->Consts, + (const float (*)[4])machine->Consts[0], (const float (*)[4])shader->immediates, machine->InterpCoefs /*, &machine->QuadPos*/ diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index 7f573aef3c..98c08eaffa 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -526,6 +526,8 @@ static void sp_vbuf_destroy(struct vbuf_render *vbr) { struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); + if(cvbr->vertex_buffer) + align_free(cvbr->vertex_buffer); sp_setup_destroy_context(cvbr->setup); FREE(cvbr); } @@ -541,7 +543,6 @@ sp_create_vbuf_backend(struct softpipe_context *sp) assert(sp->draw); - cvbr->base.max_indices = SP_MAX_VBUF_INDEXES; cvbr->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE; diff --git a/src/gallium/drivers/softpipe/sp_quad_blend.c b/src/gallium/drivers/softpipe/sp_quad_blend.c index d9babe81da..d65307b7f6 100644 --- a/src/gallium/drivers/softpipe/sp_quad_blend.c +++ b/src/gallium/drivers/softpipe/sp_quad_blend.c @@ -35,7 +35,6 @@ #include "util/u_memory.h" #include "sp_context.h" #include "sp_quad.h" -#include "sp_surface.h" #include "sp_tile_cache.h" #include "sp_quad_pipe.h" @@ -224,7 +223,8 @@ logicop_quad(struct quad_stage *qs, static void blend_quad(struct quad_stage *qs, float (*quadColor)[4], - float (*dest)[4]) + float (*dest)[4], + unsigned cbuf) { static const float zero[4] = { 0, 0, 0, 0 }; static const float one[4] = { 1, 1, 1, 1 }; @@ -234,7 +234,7 @@ blend_quad(struct quad_stage *qs, /* * Compute src/first term RGB */ - switch (softpipe->blend->rgb_src_factor) { + switch (softpipe->blend->rt[cbuf].rgb_src_factor) { case PIPE_BLENDFACTOR_ONE: VEC4_COPY(source[0], quadColor[0]); /* R */ VEC4_COPY(source[1], quadColor[1]); /* G */ @@ -384,7 +384,7 @@ blend_quad(struct quad_stage *qs, /* * Compute src/first term A */ - switch (softpipe->blend->alpha_src_factor) { + switch (softpipe->blend->rt[cbuf].alpha_src_factor) { case PIPE_BLENDFACTOR_ONE: VEC4_COPY(source[3], quadColor[3]); /* A */ break; @@ -453,7 +453,7 @@ blend_quad(struct quad_stage *qs, /* * Compute dest/second term RGB */ - switch (softpipe->blend->rgb_dst_factor) { + switch (softpipe->blend->rt[cbuf].rgb_dst_factor) { case PIPE_BLENDFACTOR_ONE: /* dest = dest * 1 NO-OP, leave dest as-is */ break; @@ -593,7 +593,7 @@ blend_quad(struct quad_stage *qs, /* * Compute dest/second term A */ - switch (softpipe->blend->alpha_dst_factor) { + switch (softpipe->blend->rt[cbuf].alpha_dst_factor) { case PIPE_BLENDFACTOR_ONE: /* dest = dest * 1 NO-OP, leave dest as-is */ break; @@ -656,7 +656,7 @@ blend_quad(struct quad_stage *qs, /* * Combine RGB terms */ - switch (softpipe->blend->rgb_func) { + switch (softpipe->blend->rt[cbuf].rgb_func) { case PIPE_BLEND_ADD: VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */ VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */ @@ -689,7 +689,7 @@ blend_quad(struct quad_stage *qs, /* * Combine A terms */ - switch (softpipe->blend->alpha_func) { + switch (softpipe->blend->rt[cbuf].alpha_func) { case PIPE_BLEND_ADD: VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */ break; @@ -711,26 +711,24 @@ blend_quad(struct quad_stage *qs, } static void -colormask_quad(struct quad_stage *qs, +colormask_quad(unsigned colormask, float (*quadColor)[4], float (*dest)[4]) { - struct softpipe_context *softpipe = qs->softpipe; - /* R */ - if (!(softpipe->blend->colormask & PIPE_MASK_R)) + if (!(colormask & PIPE_MASK_R)) COPY_4V(quadColor[0], dest[0]); /* G */ - if (!(softpipe->blend->colormask & PIPE_MASK_G)) + if (!(colormask & PIPE_MASK_G)) COPY_4V(quadColor[1], dest[1]); /* B */ - if (!(softpipe->blend->colormask & PIPE_MASK_B)) + if (!(colormask & PIPE_MASK_B)) COPY_4V(quadColor[2], dest[2]); /* A */ - if (!(softpipe->blend->colormask & PIPE_MASK_A)) + if (!(colormask & PIPE_MASK_A)) COPY_4V(quadColor[3], dest[3]); } @@ -773,12 +771,12 @@ blend_fallback(struct quad_stage *qs, if (blend->logicop_enable) { logicop_quad( qs, quadColor, dest ); } - else if (blend->blend_enable) { - blend_quad( qs, quadColor, dest ); + else if (blend->rt[cbuf].blend_enable) { + blend_quad( qs, quadColor, dest, cbuf ); } - if (blend->colormask != 0xf) - colormask_quad( qs, quadColor, dest ); + if (blend->rt[cbuf].colormask != 0xf) + colormask_quad( blend->rt[cbuf].colormask, quadColor, dest); /* Output color values */ @@ -954,23 +952,23 @@ choose_blend_quad(struct quad_stage *qs, qs->run = blend_noop; } else if (!softpipe->blend->logicop_enable && - softpipe->blend->colormask == 0xf && + softpipe->blend->rt[0].colormask == 0xf && softpipe->framebuffer.nr_cbufs == 1) { - if (!blend->blend_enable) { + if (!blend->rt[0].blend_enable) { qs->run = single_output_color; } - else if (blend->rgb_src_factor == blend->alpha_src_factor && - blend->rgb_dst_factor == blend->alpha_dst_factor && - blend->rgb_func == blend->alpha_func) + else if (blend->rt[0].rgb_src_factor == blend->rt[0].alpha_src_factor && + blend->rt[0].rgb_dst_factor == blend->rt[0].alpha_dst_factor && + blend->rt[0].rgb_func == blend->rt[0].alpha_func) { - if (blend->alpha_func == PIPE_BLEND_ADD) { - if (blend->rgb_src_factor == PIPE_BLENDFACTOR_ONE && - blend->rgb_dst_factor == PIPE_BLENDFACTOR_ONE) { + if (blend->rt[0].alpha_func == PIPE_BLEND_ADD) { + if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_ONE && + blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_ONE) { qs->run = blend_single_add_one_one; } - else if (blend->rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA && - blend->rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA) + else if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA && + blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA) qs->run = blend_single_add_src_alpha_inv_src_alpha; } diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c index 0ca86c4e1c..a981775cbd 100644 --- a/src/gallium/drivers/softpipe/sp_quad_depth_test.c +++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c @@ -30,11 +30,11 @@ */ #include "pipe/p_defines.h" +#include "util/u_format.h" #include "util/u_memory.h" #include "tgsi/tgsi_scan.h" #include "sp_context.h" #include "sp_quad.h" -#include "sp_surface.h" #include "sp_quad_pipe.h" #include "sp_tile_cache.h" #include "sp_state.h" /* for sp_fragment_shader */ @@ -651,6 +651,20 @@ static unsigned mask_count[16] = +/** helper to get number of Z buffer bits */ +static unsigned +get_depth_bits(struct quad_stage *qs) +{ + struct pipe_surface *zsurf = qs->softpipe->framebuffer.zsbuf; + if (zsurf) + return util_format_get_component_bits(zsurf->format, + UTIL_FORMAT_COLORSPACE_ZS, 0); + else + return 0; +} + + + static void depth_test_quads_fallback(struct quad_stage *qs, struct quad_header *quads[], @@ -666,7 +680,7 @@ depth_test_quads_fallback(struct quad_stage *qs, nr = alpha_test_quads(qs, quads, nr); } - if (qs->softpipe->framebuffer.zsbuf && + if (get_depth_bits(qs) > 0 && (qs->softpipe->depth_stencil->depth.enabled || qs->softpipe->depth_stencil->stencil[0].enabled)) { @@ -884,7 +898,7 @@ choose_depth_test(struct quad_stage *qs, boolean alpha = qs->softpipe->depth_stencil->alpha.enabled; - boolean depth = (qs->softpipe->framebuffer.zsbuf && + boolean depth = (get_depth_bits(qs) > 0 && qs->softpipe->depth_stencil->depth.enabled); unsigned depthfunc = qs->softpipe->depth_stencil->depth.func; @@ -895,7 +909,6 @@ choose_depth_test(struct quad_stage *qs, boolean occlusion = qs->softpipe->active_query_count; - if (!alpha && !depth && !stencil) { diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c index 1e7533d0f9..ad04dc2afc 100644 --- a/src/gallium/drivers/softpipe/sp_quad_fs.c +++ b/src/gallium/drivers/softpipe/sp_quad_fs.c @@ -45,8 +45,6 @@ #include "sp_state.h" #include "sp_quad.h" #include "sp_quad_pipe.h" -#include "sp_texture.h" -#include "sp_tex_sample.h" struct quad_shade_stage @@ -109,10 +107,11 @@ shade_quads(struct quad_stage *qs, struct quad_shade_stage *qss = quad_shade_stage( qs ); struct softpipe_context *softpipe = qs->softpipe; struct tgsi_exec_machine *machine = qss->machine; - unsigned i, pass = 0; - - machine->Consts = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT]; + + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + machine->Consts[i] = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT][i]; + } machine->InterpCoefs = quads[0]->coef; for (i = 0; i < nr; i++) { diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index bd3532de4f..714a1cf534 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -91,6 +91,19 @@ softpipe_get_param(struct pipe_screen *screen, int param) return 1; case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; + case PIPE_CAP_MAX_CONST_BUFFERS: + return PIPE_MAX_CONSTANT_BUFFERS; + case PIPE_CAP_MAX_CONST_BUFFER_SIZE: + return 4096 * 4 * sizeof(float); + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 1; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 1; default: return 0; } diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c index 3da75364c5..bb1bff581c 100644 --- a/src/gallium/drivers/softpipe/sp_setup.c +++ b/src/gallium/drivers/softpipe/sp_setup.c @@ -38,10 +38,8 @@ #include "sp_setup.h" #include "sp_state.h" #include "draw/draw_context.h" -#include "draw/draw_private.h" #include "draw/draw_vertex.h" #include "pipe/p_shader_tokens.h" -#include "pipe/p_thread.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -506,21 +504,24 @@ static void tri_persp_coeff( struct setup_context *setup, /** * Special coefficient setup for gl_FragCoord. - * X and Y are trivial, though Y has to be inverted for OpenGL. + * X and Y are trivial, though Y may have to be inverted for OpenGL. * Z and W are copied from posCoef which should have already been computed. * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask. */ static void setup_fragcoord_coeff(struct setup_context *setup, uint slot) { + struct sp_fragment_shader* spfs = setup->softpipe->fs; /*X*/ - setup->coef[slot].a0[0] = 0; + setup->coef[slot].a0[0] = spfs->pixel_center_integer ? 0.0 : 0.5; setup->coef[slot].dadx[0] = 1.0; setup->coef[slot].dady[0] = 0.0; /*Y*/ - setup->coef[slot].a0[1] = 0.0; + setup->coef[slot].a0[1] = + (spfs->origin_lower_left ? setup->softpipe->framebuffer.height : 0) + + (spfs->pixel_center_integer ? 0.0 : 0.5); setup->coef[slot].dadx[1] = 0.0; - setup->coef[slot].dady[1] = 1.0; + setup->coef[slot].dady[1] = spfs->origin_lower_left ? -1.0 : 1.0; /*Z*/ setup->coef[slot].a0[2] = setup->posCoef.a0[2]; setup->coef[slot].dadx[2] = setup->posCoef.dadx[2]; diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 7f244c4fd4..a83cae7361 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -68,6 +68,9 @@ struct sp_fragment_shader { struct tgsi_shader_info info; + boolean origin_lower_left; /**< fragment shader uses lower left position origin? */ + boolean pixel_center_integer; /**< fragment shader uses integer pixel center? */ + void (*prepare)( const struct sp_fragment_shader *shader, struct tgsi_exec_machine *machine, struct tgsi_sampler **samplers); diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c index b7ed4441b4..de3edde976 100644 --- a/src/gallium/drivers/softpipe/sp_state_fs.c +++ b/src/gallium/drivers/softpipe/sp_state_fs.c @@ -44,6 +44,7 @@ softpipe_create_fs_state(struct pipe_context *pipe, { struct softpipe_context *softpipe = softpipe_context(pipe); struct sp_fragment_shader *state; + unsigned i; /* debug */ if (softpipe->dump_fs) @@ -60,6 +61,13 @@ softpipe_create_fs_state(struct pipe_context *pipe, /* get/save the summary info for this shader */ tgsi_scan_shader(templ->tokens, &state->info); + for (i = 0; i < state->info.num_properties; ++i) { + if (state->info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN) + state->origin_lower_left = state->info.properties[i].data[0]; + else if (state->info.properties[i].name == TGSI_PROPERTY_FS_COORD_PIXEL_CENTER) + state->pixel_center_integer = state->info.properties[i].data[0]; + } + return state; } @@ -164,12 +172,12 @@ softpipe_set_constant_buffer(struct pipe_context *pipe, struct softpipe_context *softpipe = softpipe_context(pipe); assert(shader < PIPE_SHADER_TYPES); - assert(index == 0); + assert(index < PIPE_MAX_CONSTANT_BUFFERS); draw_flush(softpipe->draw); /* note: reference counting */ - pipe_buffer_reference(&softpipe->constants[shader], buf); + pipe_buffer_reference(&softpipe->constants[shader][index], buf); softpipe->dirty |= SP_NEW_CONSTANTS; } diff --git a/src/gallium/drivers/softpipe/sp_state_surface.c b/src/gallium/drivers/softpipe/sp_state_surface.c index f6154109ea..3946678219 100644 --- a/src/gallium/drivers/softpipe/sp_state_surface.c +++ b/src/gallium/drivers/softpipe/sp_state_surface.c @@ -30,7 +30,6 @@ #include "sp_context.h" #include "sp_state.h" -#include "sp_surface.h" #include "sp_tile_cache.h" #include "draw/draw_context.h" diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c index 46b6991195..b491d92ed1 100644 --- a/src/gallium/drivers/softpipe/sp_state_vertex.c +++ b/src/gallium/drivers/softpipe/sp_state_vertex.c @@ -31,7 +31,6 @@ #include "sp_context.h" #include "sp_state.h" -#include "sp_surface.h" #include "draw/draw_context.h" diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index 1ae8fecacf..473ec3e150 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -517,7 +517,6 @@ compute_lambda_1d(const struct sp_sampler_varient *samp, const float p[QUAD_SIZE]) { const struct pipe_texture *texture = samp->texture; - const struct pipe_sampler_state *sampler = samp->sampler; float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); float rho = MAX2(dsdx, dsdy) * texture->width0; @@ -533,7 +532,6 @@ compute_lambda_2d(const struct sp_sampler_varient *samp, const float p[QUAD_SIZE]) { const struct pipe_texture *texture = samp->texture; - const struct pipe_sampler_state *sampler = samp->sampler; float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]); @@ -553,7 +551,6 @@ compute_lambda_3d(const struct sp_sampler_varient *samp, const float p[QUAD_SIZE]) { const struct pipe_texture *texture = samp->texture; - const struct pipe_sampler_state *sampler = samp->sampler; float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]); diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c index e50a76a73b..50242d5bd6 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c @@ -37,7 +37,6 @@ #include "util/u_tile.h" #include "util/u_math.h" #include "sp_context.h" -#include "sp_surface.h" #include "sp_texture.h" #include "sp_tex_tile_cache.h" diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index a9436a3394..a5fff91507 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -38,7 +38,6 @@ #include "util/u_memory.h" #include "sp_context.h" -#include "sp_state.h" #include "sp_texture.h" #include "sp_screen.h" #include "sp_winsys.h" @@ -57,13 +56,8 @@ softpipe_texture_layout(struct pipe_screen *screen, unsigned width = pt->width0; unsigned height = pt->height0; unsigned depth = pt->depth0; - unsigned buffer_size = 0; - pt->width0 = width; - pt->height0 = height; - pt->depth0 = depth; - for (level = 0; level <= pt->last_level; level++) { spt->stride[level] = util_format_get_stride(pt->format, width); @@ -296,6 +290,10 @@ softpipe_get_tex_transfer(struct pipe_screen *screen, assert(texture); assert(level <= texture->last_level); + /* make sure the requested region is in the image bounds */ + assert(x + w <= u_minify(texture->width0, level)); + assert(y + h <= u_minify(texture->height0, level)); + spt = CALLOC_STRUCT(softpipe_transfer); if (spt) { struct pipe_transfer *pt = &spt->base; diff --git a/src/gallium/drivers/softpipe/sp_video_context.c b/src/gallium/drivers/softpipe/sp_video_context.c index cae2d3efc5..d0723ebe9e 100644 --- a/src/gallium/drivers/softpipe/sp_video_context.c +++ b/src/gallium/drivers/softpipe/sp_video_context.c @@ -185,17 +185,18 @@ init_pipe_state(struct sp_mpeg12_context *ctx) ctx->rast = ctx->pipe->create_rasterizer_state(ctx->pipe, &rast); ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rast); - blend.blend_enable = 0; - blend.rgb_func = PIPE_BLEND_ADD; - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_func = PIPE_BLEND_ADD; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.independent_blend_enable = 0; + blend.rt[0].blend_enable = 0; + blend.rt[0].rgb_func = PIPE_BLEND_ADD; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_func = PIPE_BLEND_ADD; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; blend.logicop_enable = 0; blend.logicop_func = PIPE_LOGICOP_CLEAR; /* Needed to allow color writes to FB, even if blending disabled */ - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].colormask = PIPE_MASK_RGBA; blend.dither = 0; ctx->blend = ctx->pipe->create_blend_state(ctx->pipe, &blend); ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend); diff --git a/src/gallium/drivers/softpipe/sp_winsys.c b/src/gallium/drivers/softpipe/sp_winsys.c new file mode 100644 index 0000000000..38bcd64c6a --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_winsys.c @@ -0,0 +1,244 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + +/** + * @file + * Malloc softpipe winsys. Uses malloc for all memory allocations. + * + * @author Keith Whitwell + * @author Brian Paul + * @author Jose Fonseca + */ + + +#include "pipe/internal/p_winsys_screen.h"/* port to just p_screen */ +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "softpipe/sp_winsys.h" + + +struct st_softpipe_buffer +{ + struct pipe_buffer base; + boolean userBuffer; /** Is this a user-space buffer? */ + void *data; + void *mapped; +}; + + +/** Cast wrapper */ +static INLINE struct st_softpipe_buffer * +st_softpipe_buffer( struct pipe_buffer *buf ) +{ + return (struct st_softpipe_buffer *)buf; +} + + +static void * +st_softpipe_buffer_map(struct pipe_winsys *winsys, + struct pipe_buffer *buf, + unsigned flags) +{ + struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); + st_softpipe_buf->mapped = st_softpipe_buf->data; + return st_softpipe_buf->mapped; +} + + +static void +st_softpipe_buffer_unmap(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); + st_softpipe_buf->mapped = NULL; +} + + +static void +st_softpipe_buffer_destroy(struct pipe_buffer *buf) +{ + struct st_softpipe_buffer *oldBuf = st_softpipe_buffer(buf); + + if (oldBuf->data) { + if (!oldBuf->userBuffer) + align_free(oldBuf->data); + + oldBuf->data = NULL; + } + + FREE(oldBuf); +} + + +static void +st_softpipe_flush_frontbuffer(struct pipe_winsys *winsys, + struct pipe_surface *surf, + void *context_private) +{ +} + + + +static const char * +st_softpipe_get_name(struct pipe_winsys *winsys) +{ + return "softpipe"; +} + + +static struct pipe_buffer * +st_softpipe_buffer_create(struct pipe_winsys *winsys, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct st_softpipe_buffer *buffer = CALLOC_STRUCT(st_softpipe_buffer); + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.alignment = alignment; + buffer->base.usage = usage; + buffer->base.size = size; + + buffer->data = align_malloc(size, alignment); + + return &buffer->base; +} + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_buffer * +st_softpipe_user_buffer_create(struct pipe_winsys *winsys, + void *ptr, + unsigned bytes) +{ + struct st_softpipe_buffer *buffer; + + buffer = CALLOC_STRUCT(st_softpipe_buffer); + if(!buffer) + return NULL; + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.size = bytes; + buffer->userBuffer = TRUE; + buffer->data = ptr; + + return &buffer->base; +} + + +static struct pipe_buffer * +st_softpipe_surface_buffer_create(struct pipe_winsys *winsys, + unsigned width, unsigned height, + enum pipe_format format, + unsigned usage, + unsigned tex_usage, + unsigned *stride) +{ + const unsigned alignment = 64; + unsigned nblocksy; + + nblocksy = util_format_get_nblocksy(format, height); + *stride = align(util_format_get_stride(format, width), alignment); + + return winsys->buffer_create(winsys, alignment, + usage, + *stride * nblocksy); +} + + +static void +st_softpipe_fence_reference(struct pipe_winsys *winsys, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ +} + + +static int +st_softpipe_fence_signalled(struct pipe_winsys *winsys, + struct pipe_fence_handle *fence, + unsigned flag) +{ + return 0; +} + + +static int +st_softpipe_fence_finish(struct pipe_winsys *winsys, + struct pipe_fence_handle *fence, + unsigned flag) +{ + return 0; +} + + +static void +st_softpipe_destroy(struct pipe_winsys *winsys) +{ + FREE(winsys); +} + + +struct pipe_screen * +softpipe_create_screen_malloc(void) +{ + static struct pipe_winsys *winsys; + struct pipe_screen *screen; + + winsys = CALLOC_STRUCT(pipe_winsys); + if(!winsys) + return NULL; + + winsys->destroy = st_softpipe_destroy; + + winsys->buffer_create = st_softpipe_buffer_create; + winsys->user_buffer_create = st_softpipe_user_buffer_create; + winsys->buffer_map = st_softpipe_buffer_map; + winsys->buffer_unmap = st_softpipe_buffer_unmap; + winsys->buffer_destroy = st_softpipe_buffer_destroy; + + winsys->surface_buffer_create = st_softpipe_surface_buffer_create; + + winsys->fence_reference = st_softpipe_fence_reference; + winsys->fence_signalled = st_softpipe_fence_signalled; + winsys->fence_finish = st_softpipe_fence_finish; + + winsys->flush_frontbuffer = st_softpipe_flush_frontbuffer; + winsys->get_name = st_softpipe_get_name; + + screen = softpipe_create_screen(winsys); + if(!screen) + st_softpipe_destroy(winsys); + + return screen; +} diff --git a/src/gallium/drivers/softpipe/sp_winsys.h b/src/gallium/drivers/softpipe/sp_winsys.h index f203ded29e..3042e01a05 100644 --- a/src/gallium/drivers/softpipe/sp_winsys.h +++ b/src/gallium/drivers/softpipe/sp_winsys.h @@ -49,10 +49,17 @@ struct pipe_buffer; struct pipe_context *softpipe_create( struct pipe_screen * ); +/** + * Create a softpipe screen that uses the + * given winsys for allocating buffers. + */ +struct pipe_screen *softpipe_create_screen( struct pipe_winsys * ); -struct pipe_screen * -softpipe_create_screen(struct pipe_winsys *); - +/** + * Create a softpipe screen that uses + * regular malloc to create all its buffers. + */ +struct pipe_screen *softpipe_create_screen_malloc(void); boolean softpipe_get_texture_buffer( struct pipe_texture *texture, diff --git a/src/gallium/drivers/svga/svga_draw_arrays.c b/src/gallium/drivers/svga/svga_draw_arrays.c index 75492dffca..6b6ebc9b58 100644 --- a/src/gallium/drivers/svga/svga_draw_arrays.c +++ b/src/gallium/drivers/svga/svga_draw_arrays.c @@ -26,7 +26,6 @@ #include "svga_cmd.h" #include "pipe/p_inlines.h" -#include "util/u_prim.h" #include "indices/u_indices.h" #include "svga_hw_reg.h" diff --git a/src/gallium/drivers/svga/svga_draw_elements.c b/src/gallium/drivers/svga/svga_draw_elements.c index 167d817831..022b444eb9 100644 --- a/src/gallium/drivers/svga/svga_draw_elements.c +++ b/src/gallium/drivers/svga/svga_draw_elements.c @@ -24,7 +24,6 @@ **********************************************************/ #include "pipe/p_inlines.h" -#include "util/u_prim.h" #include "util/u_upload_mgr.h" #include "indices/u_indices.h" diff --git a/src/gallium/drivers/svga/svga_pipe_blend.c b/src/gallium/drivers/svga/svga_pipe_blend.c index 855d228755..9df5485f46 100644 --- a/src/gallium/drivers/svga/svga_pipe_blend.c +++ b/src/gallium/drivers/svga/svga_pipe_blend.c @@ -29,7 +29,6 @@ #include "util/u_memory.h" #include "svga_context.h" -#include "svga_state.h" #include "svga_hw_reg.h" @@ -182,15 +181,15 @@ svga_create_blend_state(struct pipe_context *pipe, } } else { - blend->rt[i].blend_enable = templ->blend_enable; + blend->rt[i].blend_enable = templ->rt[0].blend_enable; - if (templ->blend_enable) { - blend->rt[i].srcblend = svga_translate_blend_factor(templ->rgb_src_factor); - blend->rt[i].dstblend = svga_translate_blend_factor(templ->rgb_dst_factor); - blend->rt[i].blendeq = svga_translate_blend_func(templ->rgb_func); - blend->rt[i].srcblend_alpha = svga_translate_blend_factor(templ->alpha_src_factor); - blend->rt[i].dstblend_alpha = svga_translate_blend_factor(templ->alpha_dst_factor); - blend->rt[i].blendeq_alpha = svga_translate_blend_func(templ->alpha_func); + if (templ->rt[0].blend_enable) { + blend->rt[i].srcblend = svga_translate_blend_factor(templ->rt[0].rgb_src_factor); + blend->rt[i].dstblend = svga_translate_blend_factor(templ->rt[0].rgb_dst_factor); + blend->rt[i].blendeq = svga_translate_blend_func(templ->rt[0].rgb_func); + blend->rt[i].srcblend_alpha = svga_translate_blend_factor(templ->rt[0].alpha_src_factor); + blend->rt[i].dstblend_alpha = svga_translate_blend_factor(templ->rt[0].alpha_dst_factor); + blend->rt[i].blendeq_alpha = svga_translate_blend_func(templ->rt[0].alpha_func); if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend || blend->rt[i].dstblend_alpha != blend->rt[i].dstblend || @@ -201,7 +200,7 @@ svga_create_blend_state(struct pipe_context *pipe, } } - blend->rt[i].writemask = templ->colormask; + blend->rt[i].writemask = templ->rt[0].colormask; } return blend; diff --git a/src/gallium/drivers/svga/svga_pipe_constants.c b/src/gallium/drivers/svga/svga_pipe_constants.c index ca2c7c49d7..9022f7c439 100644 --- a/src/gallium/drivers/svga/svga_pipe_constants.c +++ b/src/gallium/drivers/svga/svga_pipe_constants.c @@ -26,13 +26,9 @@ #include "pipe/p_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" -#include "util/u_memory.h" #include "tgsi/tgsi_parse.h" #include "svga_context.h" -#include "svga_state.h" -#include "svga_hw_reg.h" -#include "svga_cmd.h" /*********************************************************************** * Constant buffers diff --git a/src/gallium/drivers/svga/svga_pipe_depthstencil.c b/src/gallium/drivers/svga/svga_pipe_depthstencil.c index df636c08a0..34e60cb341 100644 --- a/src/gallium/drivers/svga/svga_pipe_depthstencil.c +++ b/src/gallium/drivers/svga/svga_pipe_depthstencil.c @@ -29,7 +29,6 @@ #include "util/u_memory.h" #include "svga_context.h" -#include "svga_state.h" #include "svga_hw_reg.h" diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c index 0f24ef4ee8..4e0c499dc3 100644 --- a/src/gallium/drivers/svga/svga_pipe_draw.c +++ b/src/gallium/drivers/svga/svga_pipe_draw.c @@ -33,7 +33,6 @@ #include "svga_hw_reg.h" #include "svga_context.h" #include "svga_screen.h" -#include "svga_winsys.h" #include "svga_draw.h" #include "svga_state.h" #include "svga_swtnl.h" diff --git a/src/gallium/drivers/svga/svga_pipe_flush.c b/src/gallium/drivers/svga/svga_pipe_flush.c index 0becb0765a..3eb10336c4 100644 --- a/src/gallium/drivers/svga/svga_pipe_flush.c +++ b/src/gallium/drivers/svga/svga_pipe_flush.c @@ -28,13 +28,8 @@ #include "svga_screen_texture.h" #include "svga_context.h" #include "svga_winsys.h" -#include "svga_draw.h" #include "svga_debug.h" -#include "svga_hw_reg.h" - - - static void svga_flush( struct pipe_context *pipe, unsigned flags, diff --git a/src/gallium/drivers/svga/svga_pipe_fs.c b/src/gallium/drivers/svga/svga_pipe_fs.c index 5f1213e46a..32f07fb261 100644 --- a/src/gallium/drivers/svga/svga_pipe_fs.c +++ b/src/gallium/drivers/svga/svga_pipe_fs.c @@ -32,11 +32,9 @@ #include "svga_screen.h" #include "svga_context.h" -#include "svga_state.h" #include "svga_tgsi.h" #include "svga_hw_reg.h" #include "svga_cmd.h" -#include "svga_draw.h" #include "svga_debug.h" diff --git a/src/gallium/drivers/svga/svga_pipe_misc.c b/src/gallium/drivers/svga/svga_pipe_misc.c index 58cb1e6e23..8cf1f2e083 100644 --- a/src/gallium/drivers/svga/svga_pipe_misc.c +++ b/src/gallium/drivers/svga/svga_pipe_misc.c @@ -27,12 +27,6 @@ #include "svga_context.h" #include "svga_screen_texture.h" -#include "svga_state.h" -#include "svga_winsys.h" - -#include "svga_hw_reg.h" - - static void svga_set_scissor_state( struct pipe_context *pipe, diff --git a/src/gallium/drivers/svga/svga_pipe_query.c b/src/gallium/drivers/svga/svga_pipe_query.c index 01336b0a2c..08283e3731 100644 --- a/src/gallium/drivers/svga/svga_pipe_query.c +++ b/src/gallium/drivers/svga/svga_pipe_query.c @@ -32,7 +32,6 @@ #include "svga_screen.h" #include "svga_screen_buffer.h" #include "svga_winsys.h" -#include "svga_draw.h" #include "svga_debug.h" diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c index b03f8eb9cf..9ea11aad9a 100644 --- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c +++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c @@ -30,7 +30,6 @@ #include "util/u_memory.h" #include "svga_context.h" -#include "svga_state.h" #include "svga_hw_reg.h" diff --git a/src/gallium/drivers/svga/svga_pipe_sampler.c b/src/gallium/drivers/svga/svga_pipe_sampler.c index 460a101f8c..161c66dd4f 100644 --- a/src/gallium/drivers/svga/svga_pipe_sampler.c +++ b/src/gallium/drivers/svga/svga_pipe_sampler.c @@ -32,9 +32,6 @@ #include "svga_context.h" #include "svga_screen_texture.h" -#include "svga_state.h" - -#include "svga_hw_reg.h" #include "svga_debug.h" diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c index 42f290d162..724166a335 100644 --- a/src/gallium/drivers/svga/svga_pipe_vertex.c +++ b/src/gallium/drivers/svga/svga_pipe_vertex.c @@ -26,16 +26,11 @@ #include "pipe/p_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" -#include "util/u_memory.h" #include "tgsi/tgsi_parse.h" #include "svga_screen.h" #include "svga_screen_buffer.h" #include "svga_context.h" -#include "svga_state.h" -#include "svga_winsys.h" - -#include "svga_hw_reg.h" static void svga_set_vertex_buffers(struct pipe_context *pipe, diff --git a/src/gallium/drivers/svga/svga_pipe_vs.c b/src/gallium/drivers/svga/svga_pipe_vs.c index 7e6ab576ad..c4ac5304ac 100644 --- a/src/gallium/drivers/svga/svga_pipe_vs.c +++ b/src/gallium/drivers/svga/svga_pipe_vs.c @@ -33,7 +33,6 @@ #include "svga_screen.h" #include "svga_context.h" -#include "svga_state.h" #include "svga_tgsi.h" #include "svga_hw_reg.h" #include "svga_cmd.h" diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index fc1b3c980e..c9db9ac874 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -33,10 +33,8 @@ #include "svga_screen.h" #include "svga_screen_texture.h" #include "svga_screen_buffer.h" -#include "svga_cmd.h" #include "svga_debug.h" -#include "svga_hw_reg.h" #include "svga3d_shaderdefs.h" @@ -146,6 +144,13 @@ svga_get_paramf(struct pipe_screen *screen, int param) case PIPE_CAP_BLEND_EQUATION_SEPARATE: /* req. for GL 1.5 */ return 1; + 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; + default: return 0; } @@ -393,8 +398,6 @@ svga_screen_create(struct svga_winsys_screen *sws) pipe_mutex_init(svgascreen->tex_mutex); pipe_mutex_init(svgascreen->swc_mutex); - LIST_INITHEAD(&svgascreen->cached_buffers); - svga_screen_cache_init(svgascreen); return screen; diff --git a/src/gallium/drivers/svga/svga_screen.h b/src/gallium/drivers/svga/svga_screen.h index b94ca7fc1c..a009b60720 100644 --- a/src/gallium/drivers/svga/svga_screen.h +++ b/src/gallium/drivers/svga/svga_screen.h @@ -68,12 +68,6 @@ struct svga_screen pipe_mutex tex_mutex; pipe_mutex swc_mutex; /* Protects the use of swc and dirty_buffers */ - /** - * List of buffers with cached GMR. Ordered from the most recently used to - * the least recently used - */ - struct list_head cached_buffers; - struct svga_host_surface_cache cache; }; diff --git a/src/gallium/drivers/svga/svga_screen_buffer.c b/src/gallium/drivers/svga/svga_screen_buffer.c index 58a1aba464..430a6970fd 100644 --- a/src/gallium/drivers/svga/svga_screen_buffer.c +++ b/src/gallium/drivers/svga/svga_screen_buffer.c @@ -113,68 +113,9 @@ svga_buffer_destroy_hw_storage(struct svga_screen *ss, struct svga_buffer *sbuf) if(sbuf->hw.buf) { sws->buffer_destroy(sws, sbuf->hw.buf); sbuf->hw.buf = NULL; - assert(sbuf->head.prev && sbuf->head.next); - LIST_DEL(&sbuf->head); -#ifdef DEBUG - sbuf->head.next = sbuf->head.prev = NULL; -#endif } } -static INLINE enum pipe_error -svga_buffer_backup(struct svga_screen *ss, struct svga_buffer *sbuf) -{ - if (sbuf->hw.buf && sbuf->hw.num_ranges) { - void *src; - - if (!sbuf->swbuf) - sbuf->swbuf = align_malloc(sbuf->base.size, sbuf->base.alignment); - if (!sbuf->swbuf) - return PIPE_ERROR_OUT_OF_MEMORY; - - src = ss->sws->buffer_map(ss->sws, sbuf->hw.buf, - PIPE_BUFFER_USAGE_CPU_READ); - if (!src) - return PIPE_ERROR; - - memcpy(sbuf->swbuf, src, sbuf->base.size); - ss->sws->buffer_unmap(ss->sws, sbuf->hw.buf); - } - - return PIPE_OK; -} - -/** - * Try to make GMR space available by freeing the hardware storage of - * unmapped - */ -boolean -svga_buffer_free_cached_hw_storage(struct svga_screen *ss) -{ - struct list_head *curr; - struct svga_buffer *sbuf; - enum pipe_error ret = PIPE_OK; - - curr = ss->cached_buffers.prev; - - /* free the least recently used buffer's hw storage which is not mapped */ - do { - if(curr == &ss->cached_buffers) - return FALSE; - - sbuf = LIST_ENTRY(struct svga_buffer, curr, head); - - curr = curr->prev; - if (sbuf->map.count == 0) - ret = svga_buffer_backup(ss, sbuf); - - } while(sbuf->map.count != 0 || ret != PIPE_OK); - - svga_buffer_destroy_hw_storage(ss, sbuf); - - return TRUE; -} - struct svga_winsys_buffer * svga_winsys_buffer_create( struct svga_screen *ss, unsigned alignment, @@ -195,12 +136,6 @@ svga_winsys_buffer_create( struct svga_screen *ss, svga_screen_flush(ss, NULL); buf = sws->buffer_create(sws, alignment, usage, size); - SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "evicting buffers to find %d bytes GMR\n", - size); - - /* Try evicing all buffer storage */ - while(!buf && svga_buffer_free_cached_hw_storage(ss)) - buf = sws->buffer_create(sws, alignment, usage, size); } return buf; @@ -226,8 +161,6 @@ svga_buffer_create_hw_storage(struct svga_screen *ss, return PIPE_ERROR_OUT_OF_MEMORY; assert(!sbuf->needs_flush); - assert(!sbuf->head.prev && !sbuf->head.next); - LIST_ADD(&sbuf->head, &ss->cached_buffers); } return PIPE_OK; @@ -311,7 +244,6 @@ static void svga_buffer_upload_flush(struct svga_context *svga, struct svga_buffer *sbuf) { - struct svga_screen *ss = svga_screen(svga->pipe.screen); SVGA3dCopyBox *boxes; unsigned i; @@ -348,13 +280,16 @@ svga_buffer_upload_flush(struct svga_context *svga, assert(sbuf->head.prev && sbuf->head.next); LIST_DEL(&sbuf->head); +#ifdef DEBUG + sbuf->head.next = sbuf->head.prev = NULL; +#endif sbuf->needs_flush = FALSE; - /* XXX: do we care about cached_buffers any more ?*/ - LIST_ADD(&sbuf->head, &ss->cached_buffers); sbuf->hw.svga = NULL; sbuf->hw.boxes = NULL; + sbuf->host_written = TRUE; + /* Decrement reference count */ pipe_reference(&(sbuf->base.reference), NULL); sbuf = NULL; @@ -437,17 +372,17 @@ svga_buffer_map_range( struct pipe_screen *screen, } else { if(!sbuf->hw.buf) { - struct svga_winsys_surface *handle = sbuf->handle; - if(svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK) return NULL; /* Populate the hardware storage if the host surface pre-existed */ - if((usage & PIPE_BUFFER_USAGE_CPU_READ) && handle) { + if(sbuf->host_written) { SVGA3dSurfaceDMAFlags flags; enum pipe_error ret; struct pipe_fence_handle *fence = NULL; + assert(sbuf->handle); + SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "dma from sid %p (buffer), bytes %u - %u\n", sbuf->handle, 0, sbuf->base.size); @@ -478,17 +413,6 @@ svga_buffer_map_range( struct pipe_screen *screen, sws->fence_reference(sws, &fence, NULL); } } - else { - if((usage & PIPE_BUFFER_USAGE_CPU_READ) && !sbuf->needs_flush) { - /* We already had the hardware storage but we would have to issue - * a download if we hadn't, so move the buffer to the begginning - * of the LRU list. - */ - assert(sbuf->head.prev && sbuf->head.next); - LIST_DEL(&sbuf->head); - LIST_ADD(&sbuf->head, &ss->cached_buffers); - } - } map = sws->buffer_map(sws, sbuf->hw.buf, usage); } @@ -572,10 +496,8 @@ svga_buffer_destroy( struct pipe_buffer *buf ) assert(!sbuf->needs_flush); - if(sbuf->handle) { - SVGA_DBG(DEBUG_DMA, "release sid %p sz %d\n", sbuf->handle, sbuf->base.size); - svga_screen_surface_destroy(ss, &sbuf->key, &sbuf->handle); - } + if(sbuf->handle) + svga_buffer_destroy_host_surface(ss, sbuf); if(sbuf->hw.buf) svga_buffer_destroy_hw_storage(ss, sbuf); @@ -595,6 +517,9 @@ svga_buffer_create(struct pipe_screen *screen, struct svga_screen *ss = svga_screen(screen); struct svga_buffer *sbuf; + assert(size); + assert(alignment); + sbuf = CALLOC_STRUCT(svga_buffer); if(!sbuf) goto error1; @@ -755,8 +680,7 @@ svga_buffer_handle(struct svga_context *svga, assert(sbuf->hw.svga == svga); sbuf->needs_flush = TRUE; - assert(sbuf->head.prev && sbuf->head.next); - LIST_DEL(&sbuf->head); + assert(!sbuf->head.prev && !sbuf->head.next); LIST_ADDTAIL(&sbuf->head, &svga->dirty_buffers); } diff --git a/src/gallium/drivers/svga/svga_screen_buffer.h b/src/gallium/drivers/svga/svga_screen_buffer.h index 5d7af5a7c5..448ac107c7 100644 --- a/src/gallium/drivers/svga/svga_screen_buffer.h +++ b/src/gallium/drivers/svga/svga_screen_buffer.h @@ -135,6 +135,11 @@ struct svga_buffer */ struct svga_winsys_surface *handle; + /** + * Whether the host has been ever written. + */ + boolean host_written; + struct { unsigned count; boolean writing; @@ -178,9 +183,6 @@ svga_buffer_handle(struct svga_context *svga, void svga_context_flush_buffers(struct svga_context *svga); -boolean -svga_buffer_free_cached_hw_storage(struct svga_screen *ss); - struct svga_winsys_buffer * svga_winsys_buffer_create(struct svga_screen *ss, unsigned alignment, diff --git a/src/gallium/drivers/svga/svga_screen_texture.c b/src/gallium/drivers/svga/svga_screen_texture.c index 2224c2d394..0d69007fd8 100644 --- a/src/gallium/drivers/svga/svga_screen_texture.c +++ b/src/gallium/drivers/svga/svga_screen_texture.c @@ -306,11 +306,19 @@ svga_texture_create(struct pipe_screen *screen, tex->key.numFaces = 1; } + tex->key.cachable = 1; + if(templat->tex_usage & PIPE_TEXTURE_USAGE_SAMPLER) tex->key.flags |= SVGA3D_SURFACE_HINT_TEXTURE; - if(templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) + if(templat->tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { + tex->key.cachable = 0; + } + + if(templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) { tex->key.flags |= SVGA3D_SURFACE_HINT_SCANOUT; + tex->key.cachable = 0; + } /* * XXX: Never pass the SVGA3D_SURFACE_HINT_RENDERTARGET hint. Mesa cannot @@ -333,8 +341,6 @@ svga_texture_create(struct pipe_screen *screen, if(tex->key.format == SVGA3D_FORMAT_INVALID) goto error2; - tex->key.cachable = 1; - SVGA_DBG(DEBUG_DMA, "surface_create for texture\n", tex->handle); tex->handle = svga_screen_surface_create(svgascreen, &tex->key); if (tex->handle) @@ -416,6 +422,62 @@ svga_texture_blanket(struct pipe_screen * screen, } +struct pipe_texture * +svga_screen_texture_wrap_surface(struct pipe_screen *screen, + struct pipe_texture *base, + enum SVGA3dSurfaceFormat format, + struct svga_winsys_surface *srf) +{ + struct svga_texture *tex; + assert(screen); + + /* Only supports one type */ + if (base->target != PIPE_TEXTURE_2D || + base->last_level != 0 || + base->depth0 != 1) { + return NULL; + } + + if (!srf) + return NULL; + + if (svga_translate_format(base->format) != format) { + unsigned f1 = svga_translate_format(base->format); + unsigned f2 = format; + + /* It's okay for XRGB and ARGB or depth with/out stencil to get mixed up */ + if ( !( (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_A8R8G8B8) || + (f1 == SVGA3D_A8R8G8B8 && f2 == SVGA3D_X8R8G8B8) || + (f1 == SVGA3D_Z_D24X8 && f2 == SVGA3D_Z_D24S8) ) ) { + debug_printf("%s wrong format %u != %u\n", __FUNCTION__, f1, f2); + return NULL; + } + } + + tex = CALLOC_STRUCT(svga_texture); + if (!tex) + return NULL; + + tex->base = *base; + + + if (format == 1) + tex->base.format = PIPE_FORMAT_X8R8G8B8_UNORM; + else if (format == 2) + tex->base.format = PIPE_FORMAT_A8R8G8B8_UNORM; + + pipe_reference_init(&tex->base.reference, 1); + tex->base.screen = screen; + + SVGA_DBG(DEBUG_DMA, "wrap surface sid %p\n", srf); + + tex->key.cachable = 0; + tex->handle = srf; + + return &tex->base; +} + + static void svga_texture_destroy(struct pipe_texture *pt) { diff --git a/src/gallium/drivers/svga/svga_state_framebuffer.c b/src/gallium/drivers/svga/svga_state_framebuffer.c index cfdcae4ee4..eda1aefd67 100644 --- a/src/gallium/drivers/svga/svga_state_framebuffer.c +++ b/src/gallium/drivers/svga/svga_state_framebuffer.c @@ -32,8 +32,6 @@ #include "svga_cmd.h" #include "svga_debug.h" -#include "svga_hw_reg.h" - /*********************************************************************** * Hardware state update diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c index 8b6803a285..2f9adaeb56 100644 --- a/src/gallium/drivers/svga/svga_state_rss.c +++ b/src/gallium/drivers/svga/svga_state_rss.c @@ -31,9 +31,6 @@ #include "svga_state.h" #include "svga_cmd.h" -#include "svga_hw_reg.h" - - struct rs_queue { unsigned rs_count; diff --git a/src/gallium/drivers/svga/svga_state_tss.c b/src/gallium/drivers/svga/svga_state_tss.c index b313794520..b3c9687b1a 100644 --- a/src/gallium/drivers/svga/svga_state_tss.c +++ b/src/gallium/drivers/svga/svga_state_tss.c @@ -33,8 +33,6 @@ #include "svga_state.h" #include "svga_cmd.h" -#include "svga_hw_reg.h" - void svga_cleanup_tss_binding(struct svga_context *svga) { diff --git a/src/gallium/drivers/svga/svga_swtnl_backend.c b/src/gallium/drivers/svga/svga_swtnl_backend.c index b4f757a47a..aafb3e26b0 100644 --- a/src/gallium/drivers/svga/svga_swtnl_backend.c +++ b/src/gallium/drivers/svga/svga_swtnl_backend.c @@ -31,7 +31,6 @@ #include "pipe/p_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" -#include "util/u_simple_shaders.h" #include "svga_context.h" #include "svga_state.h" @@ -87,13 +86,13 @@ svga_vbuf_render_allocate_vertices( struct vbuf_render *render, if (!svga_render->vbuf) { svga_render->vbuf_size = MAX2(size, svga_render->vbuf_alloc_size); svga_render->vbuf = pipe_buffer_create(screen, - 0, + 16, PIPE_BUFFER_USAGE_VERTEX, svga_render->vbuf_size); if(!svga_render->vbuf) { svga_context_flush(svga, NULL); svga_render->vbuf = pipe_buffer_create(screen, - 0, + 16, PIPE_BUFFER_USAGE_VERTEX, svga_render->vbuf_size); assert(svga_render->vbuf); @@ -123,7 +122,9 @@ svga_vbuf_render_map_vertices( struct vbuf_render *render ) char *ptr = (char*)pipe_buffer_map(screen, svga_render->vbuf, PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_FLUSH_EXPLICIT); + PIPE_BUFFER_USAGE_FLUSH_EXPLICIT | + PIPE_BUFFER_USAGE_DISCARD | + PIPE_BUFFER_USAGE_UNSYNCHRONIZED); return ptr + svga_render->vbuf_offset; } @@ -259,14 +260,14 @@ svga_vbuf_render_draw( struct vbuf_render *render, if (!svga_render->ibuf) { svga_render->ibuf_size = MAX2(size, svga_render->ibuf_alloc_size); svga_render->ibuf = pipe_buffer_create(screen, - 0, + 2, PIPE_BUFFER_USAGE_VERTEX, svga_render->ibuf_size); svga_render->ibuf_offset = 0; } - pipe_buffer_write(screen, svga_render->ibuf, - svga_render->ibuf_offset, 2 * nr_indices, indices); + pipe_buffer_write_nooverlap(screen, svga_render->ibuf, + svga_render->ibuf_offset, 2 * nr_indices, indices); /* off to hardware */ diff --git a/src/gallium/drivers/svga/svga_swtnl_draw.c b/src/gallium/drivers/svga/svga_swtnl_draw.c index 7655121bec..5e6e30c7df 100644 --- a/src/gallium/drivers/svga/svga_swtnl_draw.c +++ b/src/gallium/drivers/svga/svga_swtnl_draw.c @@ -27,7 +27,6 @@ #include "draw/draw_vbuf.h" #include "pipe/p_inlines.h" #include "pipe/p_state.h" -#include "util/u_memory.h" #include "svga_context.h" #include "svga_swtnl.h" @@ -90,7 +89,7 @@ svga_swtnl_draw_range_elements(struct svga_context *svga, PIPE_BUFFER_USAGE_CPU_READ); assert(map); draw_set_mapped_constant_buffer( - draw, PIPE_SHADER_VERTEX, + draw, PIPE_SHADER_VERTEX, 0, map, svga->curr.cb[PIPE_SHADER_VERTEX]->size); } diff --git a/src/gallium/drivers/svga/svga_swtnl_state.c b/src/gallium/drivers/svga/svga_swtnl_state.c index 94b6ccc62d..fe03e207ff 100644 --- a/src/gallium/drivers/svga/svga_swtnl_state.c +++ b/src/gallium/drivers/svga/svga_swtnl_state.c @@ -27,7 +27,6 @@ #include "draw/draw_vbuf.h" #include "pipe/p_inlines.h" #include "pipe/p_state.h" -#include "util/u_memory.h" #include "svga_context.h" #include "svga_swtnl.h" diff --git a/src/gallium/drivers/svga/svga_tgsi_decl_sm20.c b/src/gallium/drivers/svga/svga_tgsi_decl_sm20.c index 23b3ace7f3..1ae9906761 100644 --- a/src/gallium/drivers/svga/svga_tgsi_decl_sm20.c +++ b/src/gallium/drivers/svga/svga_tgsi_decl_sm20.c @@ -29,9 +29,6 @@ #include "util/u_memory.h" #include "svga_tgsi_emit.h" -#include "svga_context.h" - - static boolean ps20_input( struct svga_shader_emitter *emit, diff --git a/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c b/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c index d1c7336dec..43fc0d3235 100644 --- a/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c +++ b/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c @@ -29,7 +29,6 @@ #include "util/u_memory.h" #include "svga_tgsi_emit.h" -#include "svga_context.h" static boolean translate_vs_ps_semantic( struct tgsi_declaration_semantic semantic, unsigned *usage, diff --git a/src/gallium/drivers/svga/svga_winsys.h b/src/gallium/drivers/svga/svga_winsys.h index 59f299c185..27b99fe4c1 100644 --- a/src/gallium/drivers/svga/svga_winsys.h +++ b/src/gallium/drivers/svga/svga_winsys.h @@ -296,4 +296,10 @@ svga_screen_buffer_from_texture(struct pipe_texture *texture, struct pipe_buffer **buffer, unsigned *stride); +struct pipe_texture * +svga_screen_texture_wrap_surface(struct pipe_screen *screen, + struct pipe_texture *base, + enum SVGA3dSurfaceFormat format, + struct svga_winsys_surface *srf); + #endif /* SVGA_WINSYS_H_ */ diff --git a/src/gallium/drivers/trace/tr_drm.c b/src/gallium/drivers/trace/tr_drm.c index 48d1c4051c..e7ca3a86ea 100644 --- a/src/gallium/drivers/trace/tr_drm.c +++ b/src/gallium/drivers/trace/tr_drm.c @@ -173,6 +173,7 @@ trace_drm_create(struct drm_api *api) if (!tr_api) goto error; + tr_api->base.driver_name = api->driver_name; tr_api->base.create_screen = trace_drm_create_screen; tr_api->base.create_context = trace_drm_create_context; tr_api->base.texture_from_shared_handle = trace_drm_texture_from_shared_handle; diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c index 32f61f8c94..dbca5de0a5 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -323,9 +323,23 @@ void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_ trace_dump_struct_end(); } +static void trace_dump_rt_blend_state(const struct pipe_rt_blend_state *state) +{ + trace_dump_member(uint, state, rgb_func); + trace_dump_member(uint, state, rgb_src_factor); + trace_dump_member(uint, state, rgb_dst_factor); + + trace_dump_member(uint, state, alpha_func); + trace_dump_member(uint, state, alpha_src_factor); + trace_dump_member(uint, state, alpha_dst_factor); + + trace_dump_member(uint, state, colormask); + +} void trace_dump_blend_state(const struct pipe_blend_state *state) { + unsigned valid_entries = 1; if (!trace_dumping_enabled_locked()) return; @@ -336,21 +350,17 @@ void trace_dump_blend_state(const struct pipe_blend_state *state) trace_dump_struct_begin("pipe_blend_state"); - trace_dump_member(bool, state, blend_enable); - - trace_dump_member(uint, state, rgb_func); - trace_dump_member(uint, state, rgb_src_factor); - trace_dump_member(uint, state, rgb_dst_factor); - - trace_dump_member(uint, state, alpha_func); - trace_dump_member(uint, state, alpha_src_factor); - trace_dump_member(uint, state, alpha_dst_factor); + trace_dump_member(bool, state, dither); trace_dump_member(bool, state, logicop_enable); trace_dump_member(uint, state, logicop_func); - trace_dump_member(uint, state, colormask); - trace_dump_member(bool, state, dither); + trace_dump_member(bool, state, independent_blend_enable); + + if (state->independent_blend_enable) + valid_entries = PIPE_MAX_COLOR_BUFS; + + trace_dump_struct_array(rt_blend_state, state->rt, valid_entries); trace_dump_struct_end(); } diff --git a/src/gallium/include/pipe/p_compiler.h b/src/gallium/include/pipe/p_compiler.h index 18ebd0c948..6a9018aa3a 100644 --- a/src/gallium/include/pipe/p_compiler.h +++ b/src/gallium/include/pipe/p_compiler.h @@ -63,7 +63,7 @@ #include <stdbool.h> -#ifndef __HAIKU__ +#if !defined(__HAIKU__) && !defined(__USE_MISC) typedef unsigned int uint; typedef unsigned short ushort; #endif @@ -104,7 +104,8 @@ typedef unsigned char boolean; /* Function visibility */ #ifndef PUBLIC -# if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303 +# if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303) \ + || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) # define PUBLIC __attribute__((visibility("default"))) # else # define PUBLIC @@ -140,7 +141,7 @@ typedef unsigned char boolean; /* Macros for data alignment. */ -#if defined(__GNUC__) +#if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) /* See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Type-Attributes.html */ #define PIPE_ALIGN_TYPE(_alignment, _type) _type __attribute__((aligned(_alignment))) @@ -162,6 +163,13 @@ typedef unsigned char boolean; #define PIPE_ALIGN_STACK +#elif defined(SWIG) + +#define PIPE_ALIGN_TYPE(_alignment, _type) _type +#define PIPE_ALIGN_VAR(_alignment) + +#define PIPE_ALIGN_STACK + #else #error "Unsupported compiler" diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 0b8f6da2f4..f1e6a60e04 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -103,7 +103,7 @@ struct pipe_context { /** * Predicate subsequent rendering on occlusion query result * \param query the query predicate, or NULL if no predicate - * \param mode one of PIPE_COND_RENDER_x + * \param mode one of PIPE_RENDER_COND_x */ void (*render_condition)( struct pipe_context *pipe, struct pipe_query *query, @@ -122,6 +122,11 @@ struct pipe_context { void (*begin_query)(struct pipe_context *pipe, struct pipe_query *q); void (*end_query)(struct pipe_context *pipe, struct pipe_query *q); + /** + * Get results of a query. + * \param wait if true, this query will block until the result is ready + * \return TRUE if results are ready, FALSE otherwise + */ boolean (*get_query_result)(struct pipe_context *pipe, struct pipe_query *q, boolean wait, @@ -271,30 +276,30 @@ struct pipe_context { /** * Check whether a texture is referenced by an unflushed hw command. - * The state-tracker uses this function to optimize away unnecessary - * flushes. It is safe (but wasteful) to always return. + * The state-tracker uses this function to avoid unnecessary flushes. + * It is safe (but wasteful) to always return * PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE. - * \param pipe The pipe context whose unflushed hw commands will be - * checked. - * \param level mipmap level. + * \param pipe context whose unflushed hw commands will be checked. * \param texture texture to check. * \param face cubemap face. Use 0 for non-cubemap texture. + * \param level mipmap level. + * \return mask of PIPE_REFERENCED_FOR_READ/WRITE or PIPE_UNREFERENCED */ - unsigned int (*is_texture_referenced) (struct pipe_context *pipe, - struct pipe_texture *texture, - unsigned face, unsigned level); + unsigned int (*is_texture_referenced)(struct pipe_context *pipe, + struct pipe_texture *texture, + unsigned face, unsigned level); /** * Check whether a buffer is referenced by an unflushed hw command. - * The state-tracker uses this function to optimize away unnecessary - * flushes. It is safe (but wasteful) to always return + * The state-tracker uses this function to avoid unnecessary flushes. + * It is safe (but wasteful) to always return * PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE. - * \param pipe The pipe context whose unflushed hw commands will be - * checked. - * \param buf Buffer to check. + * \param pipe context whose unflushed hw commands will be checked. + * \param buf buffer to check. + * \return mask of PIPE_REFERENCED_FOR_READ/WRITE or PIPE_UNREFERENCED */ - unsigned int (*is_buffer_referenced) (struct pipe_context *pipe, - struct pipe_buffer *buf); + unsigned int (*is_buffer_referenced)(struct pipe_context *pipe, + struct pipe_buffer *buf); }; diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 35f3830ebc..63ba3119b8 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -377,7 +377,7 @@ enum pipe_transfer_usage { #define PIPE_CAP_NPOT_TEXTURES 2 #define PIPE_CAP_TWO_SIDED_STENCIL 3 #define PIPE_CAP_GLSL 4 /* XXX need something better */ -#define PIPE_CAP_S3TC 5 /* XXX: deprecated; cap determined via supported sampler formats */ +#define PIPE_CAP_DUAL_SOURCE_BLEND 5 #define PIPE_CAP_ANISOTROPIC_FILTER 6 #define PIPE_CAP_POINT_SPRITE 7 #define PIPE_CAP_MAX_RENDER_TARGETS 8 @@ -405,6 +405,14 @@ enum pipe_transfer_usage { #define PIPE_CAP_MAX_PREDICATE_REGISTERS 30 #define PIPE_CAP_MAX_COMBINED_SAMPLERS 31 /*< Maximum texture image units accessible from vertex and fragment shaders combined */ +#define PIPE_CAP_MAX_CONST_BUFFERS 32 +#define PIPE_CAP_MAX_CONST_BUFFER_SIZE 33 /*< In bytes */ +#define PIPE_CAP_INDEP_BLEND_ENABLE 34 /*< blend enables and write masks per rendertarget */ +#define PIPE_CAP_INDEP_BLEND_FUNC 35 /*< different blend funcs per rendertarget */ +#define PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT 36 +#define PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT 37 +#define PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER 38 +#define PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER 39 /** diff --git a/src/gallium/include/pipe/p_inlines.h b/src/gallium/include/pipe/p_inlines.h index 5fbd62a03d..72f5c1dc2a 100644 --- a/src/gallium/include/pipe/p_inlines.h +++ b/src/gallium/include/pipe/p_inlines.h @@ -63,13 +63,6 @@ pipe_buffer_map(struct pipe_screen *screen, if(screen->buffer_map_range) { unsigned offset = 0; unsigned length = buf->size; - - /* XXX: Actually we should be using/detecting DISCARD - * instead of assuming that WRITE implies discard */ - if((usage & PIPE_BUFFER_USAGE_CPU_WRITE) && - !(usage & PIPE_BUFFER_USAGE_DISCARD)) - usage |= PIPE_BUFFER_USAGE_CPU_READ; - return screen->buffer_map_range(screen, buf, offset, length, usage); } else @@ -126,7 +119,39 @@ pipe_buffer_write(struct pipe_screen *screen, map = pipe_buffer_map_range(screen, buf, offset, size, PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_FLUSH_EXPLICIT); + PIPE_BUFFER_USAGE_FLUSH_EXPLICIT | + PIPE_BUFFER_USAGE_DISCARD); + assert(map); + if(map) { + memcpy((uint8_t *)map + offset, data, size); + pipe_buffer_flush_mapped_range(screen, buf, offset, size); + pipe_buffer_unmap(screen, buf); + } +} + +/** + * Special case for writing non-overlapping ranges. + * + * We can avoid GPU/CPU synchronization when writing range that has never + * been written before. + */ +static INLINE void +pipe_buffer_write_nooverlap(struct pipe_screen *screen, + struct pipe_buffer *buf, + unsigned offset, unsigned size, + const void *data) +{ + void *map; + + assert(offset < buf->size); + assert(offset + size <= buf->size); + assert(size); + + map = pipe_buffer_map_range(screen, buf, offset, size, + PIPE_BUFFER_USAGE_CPU_WRITE | + PIPE_BUFFER_USAGE_FLUSH_EXPLICIT | + PIPE_BUFFER_USAGE_DISCARD | + PIPE_BUFFER_USAGE_UNSYNCHRONIZED); assert(map); if(map) { memcpy((uint8_t *)map + offset, data, size); diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index b489b04466..21581a4674 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -109,10 +109,11 @@ struct tgsi_declaration unsigned File : 4; /**< one of TGSI_FILE_x */ unsigned UsageMask : 4; /**< bitmask of TGSI_WRITEMASK_x flags */ unsigned Interpolate : 4; /**< one of TGSI_INTERPOLATE_x */ + unsigned Dimension : 1; /**< any extra dimension info? */ unsigned Semantic : 1; /**< BOOL, any semantic info? */ unsigned Centroid : 1; /**< centroid sampling? */ unsigned Invariant : 1; /**< invariant optimization? */ - unsigned Padding : 5; + unsigned Padding : 4; }; struct tgsi_declaration_range @@ -121,6 +122,12 @@ struct tgsi_declaration_range unsigned Last : 16; /**< UINT */ }; +struct tgsi_declaration_dimension +{ + unsigned Index2D:16; /**< UINT */ + unsigned Padding:16; +}; + #define TGSI_SEMANTIC_POSITION 0 #define TGSI_SEMANTIC_COLOR 1 #define TGSI_SEMANTIC_BCOLOR 2 /**< back-face color */ @@ -163,7 +170,9 @@ union tgsi_immediate_data #define TGSI_PROPERTY_GS_INPUT_PRIM 0 #define TGSI_PROPERTY_GS_OUTPUT_PRIM 1 #define TGSI_PROPERTY_GS_MAX_VERTICES 2 -#define TGSI_PROPERTY_COUNT 3 +#define TGSI_PROPERTY_FS_COORD_ORIGIN 3 +#define TGSI_PROPERTY_FS_COORD_PIXEL_CENTER 4 +#define TGSI_PROPERTY_COUNT 5 struct tgsi_property { unsigned Type : 4; /**< TGSI_TOKEN_TYPE_PROPERTY */ @@ -172,6 +181,12 @@ struct tgsi_property { unsigned Padding : 12; }; +#define TGSI_FS_COORD_ORIGIN_UPPER_LEFT 0 +#define TGSI_FS_COORD_ORIGIN_LOWER_LEFT 1 + +#define TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER 0 +#define TGSI_FS_COORD_PIXEL_CENTER_INTEGER 1 + struct tgsi_property_data { unsigned Data; }; diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index fdd29ed449..03cd74efed 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -58,7 +58,7 @@ extern "C" { #define PIPE_MAX_ATTRIBS 32 #define PIPE_MAX_CLIP_PLANES 6 #define PIPE_MAX_COLOR_BUFS 8 -#define PIPE_MAX_CONSTANT 32 +#define PIPE_MAX_CONSTANT_BUFFERS 32 #define PIPE_MAX_SAMPLERS 16 #define PIPE_MAX_VERTEX_SAMPLERS 16 #define PIPE_MAX_SHADER_INPUTS 16 @@ -217,7 +217,7 @@ struct pipe_depth_stencil_alpha_state }; -struct pipe_blend_state +struct pipe_rt_blend_state { unsigned blend_enable:1; @@ -229,11 +229,16 @@ struct pipe_blend_state unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */ unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ + unsigned colormask:4; /**< bitmask of PIPE_MASK_R/G/B/A */ +}; + +struct pipe_blend_state +{ + unsigned independent_blend_enable:1; unsigned logicop_enable:1; unsigned logicop_func:4; /**< PIPE_LOGICOP_x */ - - unsigned colormask:4; /**< bitmask of PIPE_MASK_R/G/B/A */ unsigned dither:1; + struct pipe_rt_blend_state rt[PIPE_MAX_COLOR_BUFS]; }; @@ -269,7 +274,7 @@ struct pipe_sampler_state unsigned compare_mode:1; /**< PIPE_TEX_COMPARE_x */ unsigned compare_func:3; /**< PIPE_FUNC_x */ unsigned normalized_coords:1; /**< Are coords normalized to [0,1]? */ - unsigned prefilter:4; /**< Wierd sampling state exposed by some api's */ + unsigned prefilter:4; /**< Cylindrical texcoord wrap, per coord, exposed by some api's */ float lod_bias; /**< LOD/lambda bias */ float min_lod, max_lod; /**< LOD clamp range, after bias */ float border_color[4]; diff --git a/src/gallium/include/state_tracker/drm_api.h b/src/gallium/include/state_tracker/drm_api.h index bb928928c9..b248a81880 100644 --- a/src/gallium/include/state_tracker/drm_api.h +++ b/src/gallium/include/state_tracker/drm_api.h @@ -31,6 +31,11 @@ struct drm_api const char *name; /** + * Kernel driver name, as accepted by drmOpenByName. + */ + const char *driver_name; + + /** * Special buffer functions */ /*@{*/ diff --git a/src/gallium/state_trackers/Makefile b/src/gallium/state_trackers/Makefile index 265ca468c2..0900efc664 100644 --- a/src/gallium/state_trackers/Makefile +++ b/src/gallium/state_trackers/Makefile @@ -21,5 +21,9 @@ clean: rm -f `find . -name depend` -# Dummy install target install: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE) $@) || exit 1 ; \ + fi \ + done diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c index f2e5f3fb23..07f0554cc0 100644 --- a/src/gallium/state_trackers/dri/dri_context.c +++ b/src/gallium/state_trackers/dri/dri_context.c @@ -101,6 +101,12 @@ dri_destroy_context(__DRIcontext * cPriv) { struct dri_context *ctx = dri_context(cPriv); + /* note: we are freeing values and nothing more because + * driParseConfigFiles allocated values only - the rest + * is owned by screen optionCache. + */ + FREE(ctx->optionCache.values); + /* No particular reason to wait for command completion before * destroying a context, but it is probably worthwhile flushing it * to avoid having to add code elsewhere to cope with flushing a diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c index 0fdfa96b35..1f456cb829 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -35,7 +35,6 @@ #include "pipe/p_context.h" #include "pipe/p_screen.h" -#include "pipe/p_inlines.h" #include "main/mtypes.h" #include "main/renderbuffer.h" #include "state_tracker/drm_api.h" @@ -123,11 +122,12 @@ dri_get_buffers(__DRIdrawable * dPriv) struct dri_drawable *drawable = dri_drawable(dPriv); struct pipe_surface *surface = NULL; - struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen; + struct dri_screen *st_screen = dri_screen(drawable->sPriv); + struct pipe_screen *screen = st_screen->pipe_screen; __DRIbuffer *buffers = NULL; __DRIscreen *dri_screen = drawable->sPriv; __DRIdrawable *dri_drawable = drawable->dPriv; - struct drm_api *api = ((struct dri_screen*)(dri_screen->private))->api; + struct drm_api *api = st_screen->api; boolean have_depth = FALSE; int i, count; @@ -180,7 +180,9 @@ dri_get_buffers(__DRIdrawable * dPriv) switch (buffers[i].attachment) { case __DRI_BUFFER_FRONT_LEFT: - continue; + if (!st_screen->auto_fake_front) + continue; + /* fallthrough */ case __DRI_BUFFER_FAKE_FRONT_LEFT: index = ST_SURFACE_FRONT_LEFT; format = drawable->color_format; @@ -373,8 +375,8 @@ dri_create_buffer(__DRIscreen * sPriv, /* TODO incase of double buffer visual, delay fake creation */ i = 0; drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT; - drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; - + if (!screen->auto_fake_front) + drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; if (visual->doubleBufferMode) drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT; if (visual->depthBits && visual->stencilBits) diff --git a/src/gallium/state_trackers/dri/dri_extensions.c b/src/gallium/state_trackers/dri/dri_extensions.c index 8b014a2a8b..1259813a41 100644 --- a/src/gallium/state_trackers/dri/dri_extensions.c +++ b/src/gallium/state_trackers/dri/dri_extensions.c @@ -50,6 +50,7 @@ #define need_GL_EXT_blend_func_separate #define need_GL_EXT_blend_minmax #define need_GL_EXT_cull_vertex +#define need_GL_EXT_draw_buffers2 #define need_GL_EXT_fog_coord #define need_GL_EXT_framebuffer_object #define need_GL_EXT_multi_draw_arrays @@ -98,6 +99,7 @@ static const struct dri_extension card_extensions[] = { {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions}, {"GL_EXT_blend_subtract", NULL}, {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions}, + {"GL_EXT_draw_buffers2", GL_EXT_draw_buffers2_functions}, {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions}, {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions}, {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions}, @@ -130,6 +132,9 @@ dri_init_extensions(struct dri_context *ctx) /* The card_extensions list should be pruned according to the * capabilities of the pipe_screen. This is actually something * that can/should be done inside st_create_context(). + * XXX Not pruning is very bogus. Always all these extensions above + * will be advertized, regardless what st_init_extensions + * (which depends on the pipe cap bits) does. */ driInitExtensions(ctx->st->ctx, card_extensions, GL_TRUE); } diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c index 793db087ee..a412b81256 100644 --- a/src/gallium/state_trackers/dri/dri_screen.c +++ b/src/gallium/state_trackers/dri/dri_screen.c @@ -37,14 +37,10 @@ #include "dri_context.h" #include "dri_drawable.h" -#include "pipe/p_context.h" #include "pipe/p_screen.h" -#include "pipe/p_inlines.h" #include "pipe/p_format.h" #include "state_tracker/drm_api.h" #include "state_tracker/dri1_api.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_cb_fbo.h" PUBLIC const char __driConfigOptions[] = DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE @@ -83,7 +79,7 @@ dri_fill_in_modes(struct dri_screen *screen, unsigned num_modes; uint8_t depth_bits_array[5]; uint8_t stencil_bits_array[5]; - uint8_t msaa_samples_array[1]; + uint8_t msaa_samples_array[2]; unsigned depth_buffer_factor; unsigned back_buffer_factor; unsigned msaa_samples_factor; @@ -147,8 +143,9 @@ dri_fill_in_modes(struct dri_screen *screen, } msaa_samples_array[0] = 0; + msaa_samples_array[1] = 4; back_buffer_factor = 3; - msaa_samples_factor = 1; + msaa_samples_factor = 2; num_modes = depth_buffer_factor * back_buffer_factor * msaa_samples_factor * 4; @@ -158,7 +155,7 @@ dri_fill_in_modes(struct dri_screen *screen, depth_bits_array, stencil_bits_array, depth_buffer_factor, back_buffer_modes, back_buffer_factor, - msaa_samples_array, 1); + msaa_samples_array, msaa_samples_factor); } else { __DRIconfig **configs_a8r8g8b8 = NULL; __DRIconfig **configs_x8r8g8b8 = NULL; @@ -170,7 +167,8 @@ dri_fill_in_modes(struct dri_screen *screen, depth_buffer_factor, back_buffer_modes, back_buffer_factor, - msaa_samples_array, 1); + msaa_samples_array, + msaa_samples_factor); if (pf_x8r8g8b8) configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV, depth_bits_array, @@ -178,7 +176,8 @@ dri_fill_in_modes(struct dri_screen *screen, depth_buffer_factor, back_buffer_modes, back_buffer_factor, - msaa_samples_array, 1); + msaa_samples_array, + msaa_samples_factor); if (configs_a8r8g8b8 && configs_x8r8g8b8) configs = driConcatConfigs(configs_x8r8g8b8, configs_a8r8g8b8); @@ -289,6 +288,8 @@ dri_init_screen2(__DRIscreen * sPriv) { struct dri_screen *screen; struct drm_create_screen_arg arg; + const __DRIdri2LoaderExtension *dri2_ext = + sPriv->dri2.loader; screen = CALLOC_STRUCT(dri_screen); if (!screen) @@ -314,6 +315,9 @@ dri_init_screen2(__DRIscreen * sPriv) driParseOptionInfo(&screen->optionCache, __driConfigOptions, __driNConfigOptions); + screen->auto_fake_front = dri2_ext->base.version >= 3 && + dri2_ext->getBuffersWithFormat != NULL; + return dri_fill_in_modes(screen, 32); fail: return NULL; @@ -323,8 +327,18 @@ static void dri_destroy_screen(__DRIscreen * sPriv) { struct dri_screen *screen = dri_screen(sPriv); + int i; screen->pipe_screen->destroy(screen->pipe_screen); + + for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) { + FREE(screen->optionCache.info[i].name); + FREE(screen->optionCache.info[i].ranges); + } + + FREE(screen->optionCache.info); + FREE(screen->optionCache.values); + FREE(screen); sPriv->private = NULL; } diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h index 03387a0e81..75a0ee4250 100644 --- a/src/gallium/state_trackers/dri/dri_screen.h +++ b/src/gallium/state_trackers/dri/dri_screen.h @@ -59,6 +59,7 @@ struct dri_screen struct pipe_screen *pipe_screen; boolean d_depth_bits_last; boolean sd_depth_bits_last; + boolean auto_fake_front; }; /** cast wrapper */ diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index e825aa718b..b696f2fae9 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -1,19 +1,75 @@ TOP = ../../../.. include $(TOP)/configs/current -LIBNAME = egldrm - -LIBRARY_INCLUDES = \ +common_INCLUDES = \ + -I. \ -I$(TOP)/src/gallium/include \ -I$(TOP)/src/gallium/auxiliary \ - -I$(TOP)/src/mesa/drivers/dri/common \ - -I$(TOP)/src/mesa \ - -I$(TOP)/include \ -I$(TOP)/src/egl/main \ + -I$(TOP)/include + +common_SOURCES = $(wildcard common/*.c) +common_OBJECTS = $(common_SOURCES:.c=.o) + + +x11_INCLUDES = \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/glx/x11 \ + -I$(TOP)/src/egl/drivers/xdri \ + -I$(TOP)/src/mesa \ $(shell pkg-config --cflags-only-I libdrm) +x11_SOURCES = $(wildcard x11/*.c) \ + $(TOP)/src/glx/x11/dri2.c \ + $(TOP)/src/egl/drivers/xdri/glxinit.c +x11_OBJECTS = $(x11_SOURCES:.c=.o) + + +kms_INCLUDES = $(shell pkg-config --cflags-only-I libdrm) +kms_SOURCES = $(wildcard kms/*.c) +kms_OBJECTS = $(kms_SOURCES:.c=.o) + + +ALL_INCLUDES = $(common_INCLUDES) $(x11_INCLUDES) $(kms_INCLUDES) +ALL_SOURCES = $(common_SOURCES) $(x11_SOURCES) $(kms_SOURCES) +ALL_OBJECTS = $(common_OBJECTS) $(x11_OBJECTS) $(kms_OBJECTS) + +##### TARGETS ##### + +EGL_DISPLAYS_MODS = $(foreach dpy, $(EGL_DISPLAYS), libegl$(dpy).a) + +default: depend $(EGL_DISPLAYS_MODS) + + +libeglx11.a: $(x11_OBJECTS) $(common_OBJECTS) Makefile + $(MKLIB) -o eglx11 -static $(x11_OBJECTS) $(common_OBJECTS) + +libeglkms.a: $(kms_OBJECTS) $(common_OBJECTS) Makefile + $(MKLIB) -o eglkms -static $(kms_OBJECTS) $(common_OBJECTS) + +depend: + rm -f depend + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(ALL_INCLUDES) $(ALL_SOURCES) 2> /dev/null + +clean: + rm -f $(ALL_OBJECTS) + rm -f $(EGL_DISPLAYS_MODS) + rm -f depend depend.bak + +# Dummy target +install: + @echo -n "" + +##### RULES ##### + +$(common_OBJECTS): %.o: %.c + $(CC) -c $(common_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ -C_SOURCES = $(wildcard ./*.c) +$(x11_OBJECTS): %.o: %.c + $(CC) -c $(common_INCLUDES) $(x11_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ +$(kms_OBJECTS): %.o: %.c + $(CC) -c $(common_INCLUDES) $(kms_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ -include ../../Makefile.template +sinclude depend diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 51da8e19f5..6c8f3b9f79 100644 --- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -26,6 +26,7 @@ #include <string.h> #include "pipe/p_screen.h" #include "util/u_memory.h" +#include "util/u_rect.h" #include "egldriver.h" #include "eglcurrent.h" #include "eglconfigutil.h" @@ -44,8 +45,13 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx) struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct pipe_screen *screen = gdpy->native->screen; struct egl_g3d_context *gctx = egl_g3d_context(ctx); - EGLint num_surfaces; - EGLint s, i; + const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = { + ST_SURFACE_FRONT_LEFT, + ST_SURFACE_BACK_LEFT, + ST_SURFACE_FRONT_RIGHT, + ST_SURFACE_BACK_RIGHT, + }; + EGLint num_surfaces, s; /* validate draw and/or read buffers */ num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2; @@ -53,6 +59,7 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx) struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; struct egl_g3d_surface *gsurf; struct egl_g3d_buffer *gbuf; + EGLint att; if (s == 0) { gsurf = egl_g3d_surface(gctx->base.DrawSurface); @@ -66,30 +73,31 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx) if (!gctx->force_validate) { unsigned int seq_num; - gsurf->native->validate(gsurf->native, - gbuf->native_atts, gbuf->num_atts, + gsurf->native->validate(gsurf->native, gbuf->attachment_mask, &seq_num, NULL, NULL, NULL); /* skip validation */ if (gsurf->sequence_number == seq_num) continue; } - gsurf->native->validate(gsurf->native, - gbuf->native_atts, gbuf->num_atts, + pipe_surface_reference(&gsurf->render_surface, NULL); + memset(textures, 0, sizeof(textures)); + + gsurf->native->validate(gsurf->native, gbuf->attachment_mask, &gsurf->sequence_number, textures, &gsurf->base.Width, &gsurf->base.Height); - for (i = 0; i < gbuf->num_atts; i++) { - struct pipe_texture *pt = textures[i]; + for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { + struct pipe_texture *pt = textures[att]; struct pipe_surface *ps; - if (pt) { + if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) { ps = screen->get_tex_surface(screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE); gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb, - gbuf->st_atts[i], ps); + st_att_map[att], ps); - if (gbuf->native_atts[i] == gsurf->render_att) + if (gsurf->render_att == att) pipe_surface_reference(&gsurf->render_surface, ps); pipe_surface_reference(&ps, NULL); @@ -128,13 +136,7 @@ static void egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx) { struct egl_g3d_context *gctx = egl_g3d_context(ctx); - const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = { - ST_SURFACE_FRONT_LEFT, - ST_SURFACE_BACK_LEFT, - ST_SURFACE_FRONT_RIGHT, - ST_SURFACE_BACK_RIGHT, - }; - EGLint s, i; + EGLint s; /* route draw and read buffers' attachments */ for (s = 0; s < 2; s++) { @@ -150,11 +152,7 @@ egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx) gbuf = &gctx->read; } - gbuf->native_atts[0] = gsurf->render_att; - gbuf->num_atts = 1; - - for (i = 0; i < gbuf->num_atts; i++) - gbuf->st_atts[i] = st_att_map[gbuf->native_atts[i]]; + gbuf->attachment_mask = (1 << gsurf->render_att); /* FIXME OpenGL defaults to draw the front or back buffer when the * context is single-buffered or double-buffered respectively. In EGL, @@ -196,19 +194,19 @@ egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx) if (!gdraw || priv != (void *) &gdraw->base) { gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); gctx->draw.st_fb = NULL; - gctx->draw.num_atts = 0; + gctx->draw.attachment_mask = 0x0; } if (is_equal) { gctx->read.st_fb = NULL; - gctx->draw.num_atts = 0; + gctx->draw.attachment_mask = 0x0; } else { priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb); if (!gread || priv != (void *) &gread->base) { gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb); gctx->read.st_fb = NULL; - gctx->draw.num_atts = 0; + gctx->draw.attachment_mask = 0x0; } } } @@ -246,17 +244,6 @@ egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx) } /** - * Return the current context of the given API. - */ -static struct egl_g3d_context * -egl_g3d_get_current_context(EGLint api) -{ - _EGLThreadInfo *t = _eglGetCurrentThread(); - EGLint api_index = _eglConvertApiToIndex(api); - return egl_g3d_context(t->CurrentContexts[api_index]); -} - -/** * Return the state tracker for the given context. */ static const struct egl_g3d_st * @@ -297,6 +284,71 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) } /** + * Initialize the state trackers. + */ +static void +egl_g3d_init_st(_EGLDriver *drv) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + EGLint i; + + /* already initialized */ + if (gdrv->api_mask) + return; + + for (i = 0; i < NUM_EGL_G3D_STS; i++) { + gdrv->stapis[i] = egl_g3d_get_st(i); + if (gdrv->stapis[i]) + gdrv->api_mask |= gdrv->stapis[i]->api_bit; + } + + if (gdrv->api_mask) + _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask); + else + _eglLog(_EGL_WARNING, "No supported client API"); +} + +/** + * Get the probe object of the display. + * + * Note that this function may be called before the display is initialized. + */ +static struct native_probe * +egl_g3d_get_probe(_EGLDriver *drv, _EGLDisplay *dpy) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + struct native_probe *nprobe; + + nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key); + if (!nprobe || nprobe->display != dpy->NativeDisplay) { + if (nprobe) + nprobe->destroy(nprobe); + nprobe = native_create_probe(dpy->NativeDisplay); + _eglSetProbeCache(gdrv->probe_key, (void *) nprobe); + } + + return nprobe; +} + +/** + * Destroy the probe object of the display. The display may be NULL. + * + * Note that this function may be called before the display is initialized. + */ +static void +egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + struct native_probe *nprobe; + + nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key); + if (nprobe && (!dpy || nprobe->display == dpy->NativeDisplay)) { + nprobe->destroy(nprobe); + _eglSetProbeCache(gdrv->probe_key, NULL); + } +} + +/** * Return an API mask that consists of the state trackers that supports the * given mode. * @@ -412,18 +464,18 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) struct egl_g3d_config *gconf; EGLBoolean valid; + gconf = CALLOC_STRUCT(egl_g3d_config); + if (!gconf) + continue; + + _eglInitConfig(&gconf->base, id); + api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask); if (!api_mask) { _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", native_configs[i]->mode.visualID); - continue; } - gconf = CALLOC_STRUCT(egl_g3d_config); - if (!gconf) - continue; - - _eglInitConfig(&gconf->base, id); valid = _eglConfigFromContextModesRec(&gconf->base, &native_configs[i]->mode, api_mask, api_mask); if (valid) { @@ -480,7 +532,7 @@ egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private) * Set force_validate to skip an unnecessary check. */ gctx->force_validate = EGL_TRUE; - egl_g3d_validate_context(gctx->base.Display, &gctx->base); + egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base); } static EGLBoolean @@ -517,6 +569,9 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); struct egl_g3d_display *gdpy; + /* the probe object is unlikely to be needed again */ + egl_g3d_destroy_probe(drv, dpy); + gdpy = CALLOC_STRUCT(egl_g3d_display); if (!gdpy) { _eglError(EGL_BAD_ALLOC, "eglInitialize"); @@ -533,6 +588,7 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer; gdpy->native->screen->update_buffer = egl_g3d_update_buffer; + egl_g3d_init_st(&gdrv->base); dpy->ClientAPIsMask = gdrv->api_mask; if (egl_g3d_add_configs(drv, dpy, 1) == 1) { @@ -605,21 +661,30 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, return &gctx->base; } -static EGLBoolean -egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +/** + * Destroy a context. + */ +static void +destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) { struct egl_g3d_context *gctx = egl_g3d_context(ctx); - if (_eglIsContextBound(&gctx->base)) - return EGL_TRUE; + /* FIXME a context might live longer than its display */ + if (!dpy->Initialized) + _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); egl_g3d_realloc_context(dpy, &gctx->base); - - /* it will destroy pipe context */ + /* it will destroy the associated pipe context */ gctx->stapi->st_destroy_context(gctx->st_ctx); free(gctx); +} +static EGLBoolean +egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + if (!_eglIsContextBound(ctx)) + destroy_context(dpy, ctx); return EGL_TRUE; } @@ -628,7 +693,7 @@ init_surface_geometry(_EGLSurface *surf) { struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - return gsurf->native->validate(gsurf->native, NULL, 0, + return gsurf->native->validate(gsurf->native, 0x0, &gsurf->sequence_number, NULL, &gsurf->base.Width, &gsurf->base.Height); } @@ -750,17 +815,28 @@ egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, return &gsurf->base; } -static EGLBoolean -egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +/** + * Destroy a surface. + */ +static void +destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) { struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - if (_eglIsSurfaceBound(&gsurf->base)) - return EGL_TRUE; + /* FIXME a surface might live longer than its display */ + if (!dpy->Initialized) + _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); pipe_surface_reference(&gsurf->render_surface, NULL); gsurf->native->destroy(gsurf->native); free(gsurf); +} + +static EGLBoolean +egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +{ + if (!_eglIsSurfaceBound(surf)) + destroy_surface(dpy, surf); return EGL_TRUE; } @@ -769,18 +845,14 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) { struct egl_g3d_context *gctx = egl_g3d_context(ctx); + struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); struct egl_g3d_context *old_gctx; - EGLint api; EGLBoolean ok = EGL_TRUE; - /* find the old context */ - api = (gctx) ? gctx->base.ClientAPI : eglQueryAPI(); - old_gctx = egl_g3d_get_current_context(api); - if (old_gctx && !_eglIsContextLinked(&old_gctx->base)) - old_gctx = NULL; - - if (!_eglMakeCurrent(drv, dpy, draw, read, ctx)) + /* bind the new context and return the "orphaned" one */ + if (!_eglBindContext(&ctx, &draw, &read)) return EGL_FALSE; + old_gctx = egl_g3d_context(ctx); if (old_gctx) { /* flush old context */ @@ -796,8 +868,6 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, } if (gctx) { - struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); - ok = egl_g3d_realloc_context(dpy, &gctx->base); if (ok) { ok = gctx->stapi->st_make_current(gctx->st_ctx, @@ -817,6 +887,13 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, old_gctx->base.WindowRenderBuffer = EGL_NONE; } + if (ctx && !_eglIsContextLinked(ctx)) + destroy_context(dpy, ctx); + if (draw && !_eglIsSurfaceLinked(draw)) + destroy_surface(dpy, draw); + if (read && read != draw && !_eglIsSurfaceLinked(read)) + destroy_surface(dpy, read); + return ok; } @@ -864,6 +941,101 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) return EGL_TRUE; } +/** + * Find a config that supports the pixmap. + */ +static _EGLConfig * +find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_config *gconf; + EGLint i; + + for (i = 0; i < dpy->NumConfigs; i++) { + gconf = egl_g3d_config(dpy->Configs[i]); + if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) + break; + } + + return (i < dpy->NumConfigs) ? &gconf->base : NULL; +} + +/** + * Get the pipe surface of the given attachment of the native surface. + */ +static struct pipe_surface * +get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf, + enum native_attachment natt) +{ + struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_surface *psurf; + + textures[natt] = NULL; + nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL); + if (!textures[natt]) + return NULL; + + psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt], + 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE); + pipe_texture_reference(&textures[natt], NULL); + + return psurf; +} + +static EGLBoolean +egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, + EGLNativePixmapType target) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + _EGLContext *ctx = _eglGetCurrentContext(); + struct egl_g3d_config *gconf; + struct native_surface *nsurf; + struct pipe_screen *screen = gdpy->native->screen; + struct pipe_surface *psurf; + + if (!gsurf->render_surface) + return EGL_TRUE; + + gconf = egl_g3d_config(find_pixmap_config(dpy, target)); + if (!gconf) + return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); + + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, + target, gconf->native); + if (!nsurf) + return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); + + /* flush if the surface is current */ + if (ctx && ctx->DrawSurface == &gsurf->base) { + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + gctx->stapi->st_flush(gctx->st_ctx, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } + + psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); + if (psurf) { + struct pipe_context pipe; + + /** + * XXX This is hacky. If we might allow the EGLDisplay to create a pipe + * context of its own and use the blitter context for this. + */ + memset(&pipe, 0, sizeof(pipe)); + pipe.screen = screen; + + util_surface_copy(&pipe, FALSE, psurf, 0, 0, + gsurf->render_surface, 0, 0, psurf->width, psurf->height); + + pipe_surface_reference(&psurf, NULL); + nsurf->flush_frontbuffer(nsurf); + } + + nsurf->destroy(nsurf); + + return EGL_TRUE; +} + static EGLBoolean egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) { @@ -875,14 +1047,15 @@ egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) static EGLBoolean egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) { - _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW); - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + _EGLContext *ctx = _eglGetCurrentContext(); if (engine != EGL_CORE_NATIVE_ENGINE) return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); - if (gsurf) + if (ctx && ctx->DrawSurface) { + struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface); gsurf->native->wait(gsurf->native); + } return EGL_TRUE; } @@ -894,6 +1067,9 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) _EGLProc proc; EGLint i; + /* in case this is called before a display is initialized */ + egl_g3d_init_st(&gdrv->base); + for (i = 0; i < NUM_EGL_G3D_STS; i++) { const struct egl_g3d_st *stapi = gdrv->stapis[i]; if (stapi) { @@ -911,7 +1087,8 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer) { struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - struct egl_g3d_context *gctx; + _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API); + struct egl_g3d_context *gctx = egl_g3d_context(ctx); enum pipe_format target_format; int target; @@ -942,14 +1119,12 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, } /* flush properly if the surface is bound */ - if (gsurf->base.Binding) { - gctx = egl_g3d_context(gsurf->base.Binding); + if (gsurf->base.CurrentContext) { + gctx = egl_g3d_context(gsurf->base.CurrentContext); gctx->stapi->st_flush(gctx->st_ctx, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); } - /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */ - gctx = egl_g3d_get_current_context(EGL_OPENGL_API); if (gctx) { if (!gsurf->render_surface) return EGL_FALSE; @@ -975,10 +1150,8 @@ egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); if (gsurf->render_surface) { - _EGLThreadInfo *t = _eglGetCurrentThread(); - /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */ - struct egl_g3d_context *gctx = egl_g3d_context( - t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]); + _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API); + struct egl_g3d_context *gctx = egl_g3d_context(ctx); /* what if the context the surface binds to is no longer current? */ if (gctx) @@ -1084,10 +1257,41 @@ egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, #endif /* EGL_MESA_screen_surface */ +static EGLint +egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy) +{ + struct native_probe *nprobe; + enum native_probe_result res; + EGLint score; + + nprobe = egl_g3d_get_probe(drv, dpy); + res = native_get_probe_result(nprobe); + + switch (res) { + case NATIVE_PROBE_UNKNOWN: + default: + score = 0; + break; + case NATIVE_PROBE_FALLBACK: + score = 40; + break; + case NATIVE_PROBE_SUPPORTED: + score = 50; + break; + case NATIVE_PROBE_EXACT: + score = 100; + break; + } + + return score; +} + static void egl_g3d_unload(_EGLDriver *drv) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + + egl_g3d_destroy_probe(drv, NULL); free(gdrv); } @@ -1096,7 +1300,6 @@ _eglMain(const char *args) { static char driver_name[64]; struct egl_g3d_driver *gdrv; - EGLint i; snprintf(driver_name, sizeof(driver_name), "Gallium/%s", native_get_name()); @@ -1117,6 +1320,7 @@ _eglMain(const char *args) gdrv->base.API.DestroySurface = egl_g3d_destroy_surface; gdrv->base.API.MakeCurrent = egl_g3d_make_current; gdrv->base.API.SwapBuffers = egl_g3d_swap_buffers; + gdrv->base.API.CopyBuffers = egl_g3d_copy_buffers; gdrv->base.API.WaitClient = egl_g3d_wait_client; gdrv->base.API.WaitNative = egl_g3d_wait_native; gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; @@ -1130,18 +1334,11 @@ _eglMain(const char *args) #endif gdrv->base.Name = driver_name; + gdrv->base.Probe = egl_g3d_probe; gdrv->base.Unload = egl_g3d_unload; - for (i = 0; i < NUM_EGL_G3D_STS; i++) { - gdrv->stapis[i] = egl_g3d_get_st(i); - if (gdrv->stapis[i]) - gdrv->api_mask |= gdrv->stapis[i]->api_bit; - } - - if (gdrv->api_mask) - _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask); - else - _eglLog(_EGL_WARNING, "No supported client API"); + /* the key is " EGL G3D" */ + gdrv->probe_key = 0x0E61063D; return &gdrv->base; } diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index 4c8b8dfe9e..3dae8c4052 100644 --- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -44,6 +44,8 @@ struct egl_g3d_driver { _EGLDriver base; const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS]; EGLint api_mask; + + EGLint probe_key; }; struct egl_g3d_display { @@ -52,9 +54,7 @@ struct egl_g3d_display { struct egl_g3d_buffer { struct st_framebuffer *st_fb; - EGLint num_atts; - enum native_attachment native_atts[NUM_NATIVE_ATTACHMENTS]; - uint st_atts[NUM_NATIVE_ATTACHMENTS]; + uint attachment_mask; }; struct egl_g3d_context { diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_st.c b/src/gallium/state_trackers/egl/common/egl_st.c index a88ff911cd..a88ff911cd 100644 --- a/src/gallium/state_trackers/egl_g3d/common/egl_st.c +++ b/src/gallium/state_trackers/egl/common/egl_st.c diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_st.h b/src/gallium/state_trackers/egl/common/egl_st.h index 8fb464bd3d..8fb464bd3d 100644 --- a/src/gallium/state_trackers/egl_g3d/common/egl_st.h +++ b/src/gallium/state_trackers/egl/common/egl_st.h diff --git a/src/gallium/state_trackers/egl_g3d/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 76f0e0c78a..72a9cec7ef 100644 --- a/src/gallium/state_trackers/egl_g3d/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -47,6 +47,27 @@ enum native_attachment { NUM_NATIVE_ATTACHMENTS }; +/** + * Enumerations for probe results. + */ +enum native_probe_result { + NATIVE_PROBE_UNKNOWN, + NATIVE_PROBE_FALLBACK, + NATIVE_PROBE_SUPPORTED, + NATIVE_PROBE_EXACT, +}; + +/** + * A probe object for display probe. + */ +struct native_probe { + int magic; + EGLNativeDisplayType display; + void *data; + + void (*destroy)(struct native_probe *nprobe); +}; + struct native_surface { void (*destroy)(struct native_surface *nsurf); @@ -64,18 +85,18 @@ struct native_surface { boolean (*flush_frontbuffer)(struct native_surface *nsurf); /** - * Validate the buffers of the surface. The returned textures are owned by - * the caller. A sequence number is also returned. The caller can use it - * to check if anything has changed since the last call. Any of the pointers - * may be NULL and it indicates the caller has no interest in those values. + * Validate the buffers of the surface. textures, if not NULL, points to an + * array of size NUM_NATIVE_ATTACHMENTS and the returned textures are owned + * by the caller. A sequence number is also returned. The caller can use + * it to check if anything has changed since the last call. Any of the + * pointers may be NULL and it indicates the caller has no interest in those + * values. * - * If this function is called multiple times with different attachments, - * those not listed in the latest call might be destroyed. This behavior - * might change in the future. + * If this function is called multiple times with different attachment + * masks, those not listed in the latest call might be destroyed. This + * behavior might change in the future. */ - boolean (*validate)(struct native_surface *nsurf, - const enum native_attachment *natts, - unsigned num_natts, + boolean (*validate)(struct native_surface *nsurf, uint attachment_mask, unsigned int *seq_num, struct pipe_texture **textures, int *width, int *height); @@ -136,6 +157,17 @@ struct native_display { int *num_configs); /** + * Test if a pixmap is supported by the given config. Required unless no + * config has GLX_PIXMAP_BIT set. + * + * This function is usually called to find a config that supports a given + * pixmap. Thus, it is usually called with the same pixmap in a row. + */ + boolean (*is_pixmap_supported)(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf); + + /** * Create a pipe context. */ struct pipe_context *(*create_context)(struct native_display *ndpy, @@ -211,6 +243,31 @@ struct native_display_modeset { const struct native_mode *nmode); }; +/** + * Test whether an attachment is set in the mask. + */ +static INLINE boolean +native_attachment_mask_test(uint mask, enum native_attachment att) +{ + return !!(mask & (1 << att)); +} + +/** + * Return a probe object for the given display. + * + * Note that the returned object may be cached and used by different native + * display modules. It allows fast probing when multiple modules probe the + * same display. + */ +struct native_probe * +native_create_probe(EGLNativeDisplayType dpy); + +/** + * Probe the probe object. + */ +enum native_probe_result +native_get_probe_result(struct native_probe *nprobe); + const char * native_get_name(void); diff --git a/src/gallium/state_trackers/egl_g3d/common/st_public_tmp.h b/src/gallium/state_trackers/egl/common/st_public_tmp.h index 507a0ec402..507a0ec402 100644 --- a/src/gallium/state_trackers/egl_g3d/common/st_public_tmp.h +++ b/src/gallium/state_trackers/egl/common/st_public_tmp.h diff --git a/src/gallium/state_trackers/egl/egl_context.c b/src/gallium/state_trackers/egl/egl_context.c deleted file mode 100644 index fee186c601..0000000000 --- a/src/gallium/state_trackers/egl/egl_context.c +++ /dev/null @@ -1,105 +0,0 @@ - -#include "utils.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "egl_tracker.h" - -#include "egllog.h" - - -#include "pipe/p_context.h" -#include "pipe/p_screen.h" - -#include "state_tracker/st_public.h" -#include "state_tracker/drm_api.h" - -#include "GL/internal/glcore.h" - -_EGLContext * -drm_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list) -{ - struct drm_device *dev = lookup_drm_device(dpy); - struct drm_context *ctx; - struct drm_context *share = NULL; - struct st_context *st_share = NULL; - int i; - __GLcontextModes *visual; - - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { - switch (attrib_list[i]) { - /* no attribs defined for now */ - default: - _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext"); - return EGL_NO_CONTEXT; - } - } - - ctx = (struct drm_context *) calloc(1, sizeof(struct drm_context)); - if (!ctx) - goto err_c; - - _eglInitContext(drv, &ctx->base, conf, attrib_list); - - ctx->pipe = dev->api->create_context(dev->api, dev->screen); - if (!ctx->pipe) - goto err_pipe; - - if (share) - st_share = share->st; - - visual = drm_visual_from_config(conf); - ctx->st = st_create_context(ctx->pipe, visual, st_share); - drm_visual_modes_destroy(visual); - - if (!ctx->st) - goto err_gl; - - return &ctx->base; - -err_gl: - ctx->pipe->destroy(ctx->pipe); -err_pipe: - free(ctx); -err_c: - return NULL; -} - -EGLBoolean -drm_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *context) -{ - struct drm_context *c = lookup_drm_context(context); - if (!_eglIsContextBound(&c->base)) { - st_destroy_context(c->st); - free(c); - } - return EGL_TRUE; -} - -EGLBoolean -drm_make_current(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *context) -{ - struct drm_surface *readSurf = lookup_drm_surface(read); - struct drm_surface *drawSurf = lookup_drm_surface(draw); - struct drm_context *ctx = lookup_drm_context(context); - EGLBoolean b; - - b = _eglMakeCurrent(drv, dpy, draw, read, context); - if (!b) - return EGL_FALSE; - - if (ctx) { - if (!drawSurf || !readSurf) - return EGL_FALSE; - - st_make_current(ctx->st, drawSurf->stfb, readSurf->stfb); - - /* st_resize_framebuffer needs a bound context to work */ - st_resize_framebuffer(drawSurf->stfb, drawSurf->w, drawSurf->h); - st_resize_framebuffer(readSurf->stfb, readSurf->w, readSurf->h); - } else { - st_make_current(NULL, NULL, NULL); - } - - return EGL_TRUE; -} diff --git a/src/gallium/state_trackers/egl/egl_surface.c b/src/gallium/state_trackers/egl/egl_surface.c deleted file mode 100644 index d55aa51b82..0000000000 --- a/src/gallium/state_trackers/egl/egl_surface.c +++ /dev/null @@ -1,443 +0,0 @@ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "egl_tracker.h" - -#include "egllog.h" - -#include "pipe/p_inlines.h" -#include "pipe/p_screen.h" -#include "pipe/p_context.h" - -#include "state_tracker/drm_api.h" - -#include "util/u_format.h" -#include "util/u_rect.h" - -/* - * Util functions - */ - -static drmModeModeInfoPtr -drm_find_mode(drmModeConnectorPtr connector, _EGLMode *mode) -{ - int i; - drmModeModeInfoPtr m = NULL; - - for (i = 0; i < connector->count_modes; i++) { - m = &connector->modes[i]; - if (m->hdisplay == mode->Width && m->vdisplay == mode->Height && m->vrefresh == mode->RefreshRate) - break; - m = &connector->modes[0]; /* if we can't find one, return first */ - } - - return m; -} - -static struct st_framebuffer * -drm_create_framebuffer(struct pipe_screen *screen, - const __GLcontextModes *visual, - unsigned width, - unsigned height, - void *priv) -{ - enum pipe_format color_format, depth_stencil_format; - boolean d_depth_bits_last; - boolean ds_depth_bits_last; - - d_depth_bits_last = - screen->is_format_supported(screen, PIPE_FORMAT_X8Z24_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - ds_depth_bits_last = - screen->is_format_supported(screen, PIPE_FORMAT_S8Z24_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - - if (visual->redBits == 8) { - if (visual->alphaBits == 8) - color_format = PIPE_FORMAT_A8R8G8B8_UNORM; - else - color_format = PIPE_FORMAT_X8R8G8B8_UNORM; - } else { - color_format = PIPE_FORMAT_R5G6B5_UNORM; - } - - switch(visual->depthBits) { - default: - case 0: - depth_stencil_format = PIPE_FORMAT_NONE; - break; - case 16: - depth_stencil_format = PIPE_FORMAT_Z16_UNORM; - break; - case 24: - if (visual->stencilBits == 0) { - depth_stencil_format = (d_depth_bits_last) ? - PIPE_FORMAT_X8Z24_UNORM: - PIPE_FORMAT_Z24X8_UNORM; - } else { - depth_stencil_format = (ds_depth_bits_last) ? - PIPE_FORMAT_S8Z24_UNORM: - PIPE_FORMAT_Z24S8_UNORM; - } - break; - case 32: - depth_stencil_format = PIPE_FORMAT_Z32_UNORM; - break; - } - - return st_create_framebuffer(visual, - color_format, - depth_stencil_format, - depth_stencil_format, - width, - height, - priv); -} - -static void -drm_create_texture(_EGLDisplay *dpy, - struct drm_screen *scrn, - unsigned w, unsigned h) -{ - struct drm_device *dev = lookup_drm_device(dpy); - struct pipe_screen *screen = dev->screen; - struct pipe_surface *surface; - struct pipe_texture *texture; - struct pipe_texture templat; - struct pipe_buffer *buf = NULL; - unsigned pitch = 0; - - memset(&templat, 0, sizeof(templat)); - templat.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; - templat.target = PIPE_TEXTURE_2D; - templat.last_level = 0; - templat.depth0 = 1; - templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; - templat.width0 = w; - templat.height0 = h; - - texture = screen->texture_create(dev->screen, - &templat); - - if (!texture) - goto err_tex; - - surface = screen->get_tex_surface(screen, - texture, - 0, - 0, - 0, - PIPE_BUFFER_USAGE_GPU_WRITE); - - if (!surface) - goto err_surf; - - scrn->tex = texture; - scrn->surface = surface; - scrn->front.width = w; - scrn->front.height = h; - scrn->front.pitch = pitch; - dev->api->local_handle_from_texture(dev->api, screen, texture, - &scrn->front.pitch, &scrn->front.handle); - if (0) - goto err_handle; - - return; - -err_handle: - pipe_surface_reference(&surface, NULL); -err_surf: - pipe_texture_reference(&texture, NULL); -err_tex: - pipe_buffer_reference(&buf, NULL); - return; -} - -/* - * Exported functions - */ - -void -drm_takedown_shown_screen(_EGLDisplay *dpy, struct drm_screen *screen) -{ - struct drm_device *dev = lookup_drm_device(dpy); - - screen->surf = NULL; - - drmModeSetCrtc( - dev->drmFD, - screen->crtcID, - 0, /* FD */ - 0, 0, - NULL, 0, /* List of output ids */ - NULL); - - drmModeRmFB(dev->drmFD, screen->fbID); - drmModeFreeFB(screen->fb); - screen->fb = NULL; - - pipe_surface_reference(&screen->surface, NULL); - pipe_texture_reference(&screen->tex, NULL); - - screen->shown = 0; -} - -/** - * Called by libEGL's eglCreateWindowSurface(). - */ -_EGLSurface * -drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list) -{ - return NULL; -} - - -/** - * Called by libEGL's eglCreatePixmapSurface(). - */ -_EGLSurface * -drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list) -{ - return NULL; -} - - -/** - * Called by libEGL's eglCreatePbufferSurface(). - */ -_EGLSurface * -drm_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - const EGLint *attrib_list) -{ - struct drm_device *dev = lookup_drm_device(dpy); - int i; - int width = -1; - int height = -1; - struct drm_surface *surf = NULL; - __GLcontextModes *visual; - - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { - switch (attrib_list[i]) { - case EGL_WIDTH: - width = attrib_list[++i]; - break; - case EGL_HEIGHT: - height = attrib_list[++i]; - break; - default: - _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface"); - return EGL_NO_SURFACE; - } - } - - if (width < 1 || height < 1) { - _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface"); - return NULL; - } - - surf = (struct drm_surface *) calloc(1, sizeof(struct drm_surface)); - if (!surf) - goto err; - - if (!_eglInitSurface(drv, &surf->base, EGL_PBUFFER_BIT, conf, attrib_list)) - goto err_surf; - - surf->w = width; - surf->h = height; - - visual = drm_visual_from_config(conf); - surf->stfb = drm_create_framebuffer(dev->screen, visual, - width, height, - (void*)surf); - drm_visual_modes_destroy(visual); - - return &surf->base; - -err_surf: - free(surf); -err: - return NULL; -} - -/** - * Called by libEGL's eglCreateScreenSurfaceMESA(). - */ -_EGLSurface * -drm_create_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *cfg, - const EGLint *attrib_list) -{ - EGLSurface surf = drm_create_pbuffer_surface(drv, dpy, cfg, attrib_list); - - return surf; -} - -/** - * Called by libEGL's eglShowScreenSurfaceMESA(). - */ -EGLBoolean -drm_show_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLScreen *screen, - _EGLSurface *surface, _EGLMode *mode) -{ - struct drm_device *dev = lookup_drm_device(dpy); - struct drm_surface *surf = lookup_drm_surface(surface); - struct drm_screen *scrn = lookup_drm_screen(screen); - int ret; - unsigned int i, k; - - if (scrn->shown) - drm_takedown_shown_screen(dpy, scrn); - - - drm_create_texture(dpy, scrn, mode->Width, mode->Height); - if (!scrn->tex) - goto err_tex; - - ret = drmModeAddFB(dev->drmFD, - scrn->front.width, scrn->front.height, - 32, 32, scrn->front.pitch, - scrn->front.handle, - &scrn->fbID); - - if (ret) - goto err_bo; - - scrn->fb = drmModeGetFB(dev->drmFD, scrn->fbID); - if (!scrn->fb) - goto err_bo; - - /* find a fitting crtc */ - { - drmModeConnector *con = scrn->connector; - - scrn->mode = drm_find_mode(con, mode); - if (!scrn->mode) - goto err_fb; - - for (k = 0; k < con->count_encoders; k++) { - drmModeEncoder *enc = drmModeGetEncoder(dev->drmFD, con->encoders[k]); - for (i = 0; i < dev->res->count_crtcs; i++) { - if (enc->possible_crtcs & (1<<i)) { - /* save the ID */ - scrn->crtcID = dev->res->crtcs[i]; - - /* skip the rest */ - i = dev->res->count_crtcs; - k = dev->res->count_encoders; - } - } - drmModeFreeEncoder(enc); - } - } - - ret = drmModeSetCrtc(dev->drmFD, - scrn->crtcID, - scrn->fbID, - 0, 0, - &scrn->connectorID, 1, - scrn->mode); - - if (ret) - goto err_crtc; - - - if (scrn->dpms) - drmModeConnectorSetProperty(dev->drmFD, - scrn->connectorID, - scrn->dpms->prop_id, - DRM_MODE_DPMS_ON); - - surf->screen = scrn; - - scrn->surf = surf; - scrn->shown = 1; - - return EGL_TRUE; - -err_crtc: - scrn->crtcID = 0; - -err_fb: - drmModeRmFB(dev->drmFD, scrn->fbID); - drmModeFreeFB(scrn->fb); - scrn->fb = NULL; - -err_bo: - pipe_surface_reference(&scrn->surface, NULL); - pipe_texture_reference(&scrn->tex, NULL); - -err_tex: - return EGL_FALSE; -} - -/** - * Called by libEGL's eglDestroySurface(). - */ -EGLBoolean -drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) -{ - struct drm_surface *surf = lookup_drm_surface(surface); - if (!_eglIsSurfaceBound(&surf->base)) { - if (surf->screen) - drm_takedown_shown_screen(dpy, surf->screen); - st_unreference_framebuffer(surf->stfb); - free(surf); - } - return EGL_TRUE; -} - -/** - * Called by libEGL's eglSwapBuffers(). - */ -EGLBoolean -drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw) -{ - struct drm_device *dev = lookup_drm_device(dpy); - struct drm_surface *surf = lookup_drm_surface(draw); - struct pipe_surface *back_surf; - - if (!surf) - return EGL_FALSE; - - st_get_framebuffer_surface(surf->stfb, ST_SURFACE_BACK_LEFT, &back_surf); - - if (back_surf) { - struct drm_context *ctx = lookup_drm_context(draw->Binding); - - st_notify_swapbuffers(surf->stfb); - - if (ctx && surf->screen) { - if (ctx->pipe->surface_copy) { - ctx->pipe->surface_copy(ctx->pipe, - surf->screen->surface, - 0, 0, - back_surf, - 0, 0, - surf->w, surf->h); - } else { - util_surface_copy(ctx->pipe, FALSE, - surf->screen->surface, - 0, 0, - back_surf, - 0, 0, - surf->w, surf->h); - } - ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE, NULL); - -#ifdef DRM_MODE_FEATURE_DIRTYFB - /* TODO query connector property to see if this is needed */ - drmModeDirtyFB(dev->drmFD, surf->screen->fbID, NULL, 0); -#else - (void)dev; -#endif - - /* TODO more stuff here */ - } - } - - return EGL_TRUE; -} diff --git a/src/gallium/state_trackers/egl/egl_tracker.c b/src/gallium/state_trackers/egl/egl_tracker.c deleted file mode 100644 index 9345b0f490..0000000000 --- a/src/gallium/state_trackers/egl/egl_tracker.c +++ /dev/null @@ -1,274 +0,0 @@ - -#include "utils.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "egl_tracker.h" - -#include <fcntl.h> - -#include "egllog.h" -#include "state_tracker/drm_api.h" - -#include "pipe/p_screen.h" -#include "pipe/internal/p_winsys_screen.h" - -/** HACK */ -void* driDriverAPI; - - -/* - * Exported functions - */ - -/** Called by libEGL just prior to unloading/closing the driver. - */ -static void -drm_unload(_EGLDriver *drv) -{ - free(drv); -} - -/** - * The bootstrap function. Return a new drm_driver object and - * plug in API functions. - * libEGL finds this function with dlopen()/dlsym() and calls it from - * "load driver" function. - */ -_EGLDriver * -_eglMain(const char *args) -{ - _EGLDriver *drv; - - drv = (_EGLDriver *) calloc(1, sizeof(_EGLDriver)); - if (!drv) { - return NULL; - } - - /* First fill in the dispatch table with defaults */ - _eglInitDriverFallbacks(drv); - /* then plug in our Drm-specific functions */ - drv->API.Initialize = drm_initialize; - drv->API.Terminate = drm_terminate; - drv->API.CreateContext = drm_create_context; - drv->API.MakeCurrent = drm_make_current; - drv->API.CreateWindowSurface = drm_create_window_surface; - drv->API.CreatePixmapSurface = drm_create_pixmap_surface; - drv->API.CreatePbufferSurface = drm_create_pbuffer_surface; - drv->API.DestroySurface = drm_destroy_surface; - drv->API.DestroyContext = drm_destroy_context; - drv->API.CreateScreenSurfaceMESA = drm_create_screen_surface_mesa; - drv->API.ShowScreenSurfaceMESA = drm_show_screen_surface_mesa; - drv->API.SwapBuffers = drm_swap_buffers; - - drv->Name = "DRM/Gallium/Win"; - drv->Unload = drm_unload; - - return drv; -} - -static void -drm_get_device_id(struct drm_device *device) -{ - char path[512]; - FILE *file; - char *ret; - - /* TODO get the real minor */ - int minor = 0; - - device->deviceID = 0; - - snprintf(path, sizeof(path), "/sys/class/drm/card%d/device/device", minor); - file = fopen(path, "r"); - if (!file) { - _eglLog(_EGL_WARNING, "Could not retrive device ID\n"); - return; - } - - ret = fgets(path, sizeof( path ), file); - fclose(file); - if (!ret) - return; - - sscanf(path, "%x", &device->deviceID); -} - -static void -drm_update_res(struct drm_device *dev) -{ - drmModeFreeResources(dev->res); - dev->res = drmModeGetResources(dev->drmFD); -} - -static void -drm_add_modes_from_connector(_EGLScreen *screen, drmModeConnectorPtr connector) -{ - drmModeModeInfoPtr m = NULL; - int i; - - for (i = 0; i < connector->count_modes; i++) { - m = &connector->modes[i]; - _eglAddNewMode(screen, m->hdisplay, m->vdisplay, m->vrefresh, m->name); - } -} - -static void -drm_find_dpms(struct drm_device *dev, struct drm_screen *screen) -{ - drmModeConnectorPtr c = screen->connector; - drmModePropertyPtr p; - int i; - - for (i = 0; i < c->count_props; i++) { - p = drmModeGetProperty(dev->drmFD, c->props[i]); - if (!strcmp(p->name, "DPMS")) - break; - - drmModeFreeProperty(p); - p = NULL; - } - - screen->dpms = p; -} - -static int drm_open_minor(int minor) -{ - char buf[64]; - - sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); - return open(buf, O_RDWR, 0); -} - -EGLBoolean -drm_initialize(_EGLDriver *drv, _EGLDisplay *disp, EGLint *major, EGLint *minor) -{ - struct drm_device *dev; - struct drm_screen *screen = NULL; - drmModeConnectorPtr connector = NULL; - drmModeResPtr res = NULL; - unsigned count_connectors = 0; - int num_screens = 0; - EGLint i; - int fd; - _EGLConfig *config; - - dev = (struct drm_device *) calloc(1, sizeof(struct drm_device)); - if (!dev) - return EGL_FALSE; - dev->api = drm_api_create(); - - /* try the first node */ - fd = drm_open_minor(0); - if (fd < 0) - goto err_fd; - - dev->drmFD = fd; - drm_get_device_id(dev); - - dev->screen = dev->api->create_screen(dev->api, dev->drmFD, NULL); - if (!dev->screen) - goto err_screen; - dev->winsys = dev->screen->winsys; - - driInitExtensions(NULL, NULL, GL_FALSE); - - drm_update_res(dev); - res = dev->res; - if (res) - count_connectors = res->count_connectors; - else - _eglLog(_EGL_WARNING, "Could not retrive kms information\n"); - - for(i = 0; i < count_connectors && i < MAX_SCREENS; i++) { - connector = drmModeGetConnector(fd, res->connectors[i]); - - if (!connector) - continue; - - if (connector->connection != DRM_MODE_CONNECTED) { - drmModeFreeConnector(connector); - continue; - } - - screen = malloc(sizeof(struct drm_screen)); - memset(screen, 0, sizeof(*screen)); - screen->connector = connector; - screen->connectorID = connector->connector_id; - _eglInitScreen(&screen->base); - _eglAddScreen(disp, &screen->base); - drm_add_modes_from_connector(&screen->base, connector); - drm_find_dpms(dev, screen); - dev->screens[num_screens++] = screen; - } - dev->count_screens = num_screens; - - disp->DriverData = dev; - - /* for now we only have one config */ - config = calloc(1, sizeof(*config)); - memset(config, 1, sizeof(*config)); - _eglInitConfig(config, 1); - _eglSetConfigAttrib(config, EGL_RED_SIZE, 8); - _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8); - _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8); - _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8); - _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32); - _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 24); - _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8); - _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT); - _eglAddConfig(disp, config); - - disp->ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/; - /* enable supported extensions */ - disp->Extensions.MESA_screen_surface = EGL_TRUE; - disp->Extensions.MESA_copy_context = EGL_TRUE; - - *major = 1; - *minor = 4; - - return EGL_TRUE; - -err_screen: - drmClose(fd); -err_fd: - free(dev); - return EGL_FALSE; -} - -EGLBoolean -drm_terminate(_EGLDriver *drv, _EGLDisplay *dpy) -{ - struct drm_device *dev = lookup_drm_device(dpy); - struct drm_screen *screen; - int i = 0; - - _eglReleaseDisplayResources(drv, dpy); - _eglCleanupDisplay(dpy); - - drmFreeVersion(dev->version); - - for (i = 0; i < dev->count_screens; i++) { - screen = dev->screens[i]; - - if (screen->shown) - drm_takedown_shown_screen(dpy, screen); - - drmModeFreeProperty(screen->dpms); - drmModeFreeConnector(screen->connector); - _eglDestroyScreen(&screen->base); - dev->screens[i] = NULL; - } - - dev->screen->destroy(dev->screen); - dev->winsys = NULL; - - drmClose(dev->drmFD); - - dev->api->destroy(dev->api); - free(dev); - dpy->DriverData = NULL; - - return EGL_TRUE; -} diff --git a/src/gallium/state_trackers/egl/egl_tracker.h b/src/gallium/state_trackers/egl/egl_tracker.h deleted file mode 100644 index 73eb1a1226..0000000000 --- a/src/gallium/state_trackers/egl/egl_tracker.h +++ /dev/null @@ -1,195 +0,0 @@ - -#ifndef _EGL_TRACKER_H_ -#define _EGL_TRACKER_H_ - -#include <stdint.h> - -#include "eglconfig.h" -#include "eglcontext.h" -#include "egldisplay.h" -#include "egldriver.h" -#include "eglglobals.h" -#include "eglmode.h" -#include "eglscreen.h" -#include "eglsurface.h" - -#include "xf86drm.h" -#include "xf86drmMode.h" - -#include "pipe/p_compiler.h" - -#include "state_tracker/st_public.h" - -#define MAX_SCREENS 16 - -struct pipe_winsys; -struct pipe_screen; -struct pipe_context; -struct state_tracker; - -struct drm_screen; -struct drm_context; - -struct drm_device -{ - /* - * pipe - */ - - struct drm_api *api; - struct pipe_winsys *winsys; - struct pipe_screen *screen; - - /* - * drm - */ - - int drmFD; - drmVersionPtr version; - int deviceID; - - drmModeResPtr res; - - struct drm_screen *screens[MAX_SCREENS]; - size_t count_screens; -}; - -struct drm_surface -{ - _EGLSurface base; /* base class/object */ - - /* - * pipe - */ - - - struct st_framebuffer *stfb; - - /* - * drm - */ - - struct drm_screen *screen; - - int w; - int h; -}; - -struct drm_context -{ - _EGLContext base; /* base class/object */ - - /* pipe */ - - struct pipe_context *pipe; - struct st_context *st; -}; - -struct drm_screen -{ - _EGLScreen base; - - /* - * pipe - */ - - struct pipe_texture *tex; - struct pipe_surface *surface; - - /* - * drm - */ - - struct { - unsigned height; - unsigned width; - unsigned pitch; - unsigned handle; - } front; - - /* currently only support one connector */ - drmModeConnectorPtr connector; - uint32_t connectorID; - - /* dpms property */ - drmModePropertyPtr dpms; - - /* Has this screen been shown */ - int shown; - - /* Surface that is currently attached to this screen */ - struct drm_surface *surf; - - /* framebuffer */ - drmModeFBPtr fb; - uint32_t fbID; - - /* crtc and mode used */ - /*drmModeCrtcPtr crtc;*/ - uint32_t crtcID; - - drmModeModeInfoPtr mode; -}; - - -static INLINE struct drm_device * -lookup_drm_device(_EGLDisplay *d) -{ - return (struct drm_device *) d->DriverData; -} - - -static INLINE struct drm_context * -lookup_drm_context(_EGLContext *c) -{ - return (struct drm_context *) c; -} - - -static INLINE struct drm_surface * -lookup_drm_surface(_EGLSurface *s) -{ - return (struct drm_surface *) s; -} - -static INLINE struct drm_screen * -lookup_drm_screen(_EGLScreen *s) -{ - return (struct drm_screen *) s; -} - -/** - * egl_visual.h - */ -/*@{*/ -void drm_visual_modes_destroy(__GLcontextModes *modes); -__GLcontextModes* drm_visual_modes_create(unsigned count, size_t minimum_size); -__GLcontextModes* drm_visual_from_config(_EGLConfig *conf); -/*@}*/ - -/** - * egl_surface.h - */ -/*@{*/ -void drm_takedown_shown_screen(_EGLDisplay *dpy, struct drm_screen *screen); -/*@}*/ - -/** - * All function exported to the egl side. - */ -/*@{*/ -EGLBoolean drm_initialize(_EGLDriver *drv, _EGLDisplay *dpy, EGLint *major, EGLint *minor); -EGLBoolean drm_terminate(_EGLDriver *drv, _EGLDisplay *dpy); -_EGLContext *drm_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list); -EGLBoolean drm_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *context); -_EGLSurface *drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list); -_EGLSurface *drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list); -_EGLSurface *drm_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list); -_EGLSurface *drm_create_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list); -EGLBoolean drm_show_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, _EGLSurface *surface, _EGLMode *mode); -EGLBoolean drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface); -EGLBoolean drm_make_current(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *context); -EGLBoolean drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw); -/*@}*/ - -#endif diff --git a/src/gallium/state_trackers/egl/egl_visual.c b/src/gallium/state_trackers/egl/egl_visual.c deleted file mode 100644 index e59f893851..0000000000 --- a/src/gallium/state_trackers/egl/egl_visual.c +++ /dev/null @@ -1,85 +0,0 @@ - -#include "egl_tracker.h" - -#include "egllog.h" - -void -drm_visual_modes_destroy(__GLcontextModes *modes) -{ - _eglLog(_EGL_DEBUG, "%s", __FUNCTION__); - - while (modes) { - __GLcontextModes * const next = modes->next; - free(modes); - modes = next; - } -} - -__GLcontextModes * -drm_visual_modes_create(unsigned count, size_t minimum_size) -{ - /* This code copied from libGLX, and modified */ - const size_t size = (minimum_size > sizeof(__GLcontextModes)) - ? minimum_size : sizeof(__GLcontextModes); - __GLcontextModes * head = NULL; - __GLcontextModes ** next; - unsigned i; - - _eglLog(_EGL_DEBUG, "%s %d %d", __FUNCTION__, count, minimum_size); - - next = & head; - for (i = 0 ; i < count ; i++) { - *next = (__GLcontextModes *) calloc(1, size); - if (*next == NULL) { - drm_visual_modes_destroy(head); - head = NULL; - break; - } - - (*next)->doubleBufferMode = 1; - (*next)->visualID = GLX_DONT_CARE; - (*next)->visualType = GLX_DONT_CARE; - (*next)->visualRating = GLX_NONE; - (*next)->transparentPixel = GLX_NONE; - (*next)->transparentRed = GLX_DONT_CARE; - (*next)->transparentGreen = GLX_DONT_CARE; - (*next)->transparentBlue = GLX_DONT_CARE; - (*next)->transparentAlpha = GLX_DONT_CARE; - (*next)->transparentIndex = GLX_DONT_CARE; - (*next)->xRenderable = GLX_DONT_CARE; - (*next)->fbconfigID = GLX_DONT_CARE; - (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; - (*next)->bindToTextureRgb = GLX_DONT_CARE; - (*next)->bindToTextureRgba = GLX_DONT_CARE; - (*next)->bindToMipmapTexture = GLX_DONT_CARE; - (*next)->bindToTextureTargets = 0; - (*next)->yInverted = GLX_DONT_CARE; - - next = & ((*next)->next); - } - - return head; -} - -__GLcontextModes * -drm_visual_from_config(_EGLConfig *conf) -{ - __GLcontextModes *visual; - (void)conf; - - visual = drm_visual_modes_create(1, sizeof(*visual)); - visual->redBits = 8; - visual->greenBits = 8; - visual->blueBits = 8; - visual->alphaBits = 8; - - visual->rgbBits = 32; - visual->doubleBufferMode = 1; - - visual->depthBits = 24; - visual->haveDepthBuffer = visual->depthBits > 0; - visual->stencilBits = 8; - visual->haveStencilBuffer = visual->stencilBits > 0; - - return visual; -} diff --git a/src/gallium/state_trackers/egl_g3d/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c index 65829fc7b3..d5baf2c2f0 100644 --- a/src/gallium/state_trackers/egl_g3d/kms/native_kms.c +++ b/src/gallium/state_trackers/egl/kms/native_kms.c @@ -33,9 +33,7 @@ #include "native_kms.h" static boolean -kms_surface_validate(struct native_surface *nsurf, - const enum native_attachment *natts, - unsigned num_natts, +kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, unsigned int *seq_num, struct pipe_texture **textures, int *width, int *height) { @@ -43,12 +41,9 @@ kms_surface_validate(struct native_surface *nsurf, struct kms_display *kdpy = ksurf->kdpy; struct pipe_screen *screen = kdpy->base.screen; struct pipe_texture templ, *ptex; - int i; - - if (num_natts) { - if (textures) - memset(textures, 0, sizeof(*textures) * num_natts); + int att; + if (attachment_mask) { memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; templ.last_level = 0; @@ -62,17 +57,21 @@ kms_surface_validate(struct native_surface *nsurf, } /* create textures */ - for (i = 0; i < num_natts; i++) { - enum native_attachment natt = natts[i]; + for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { + /* delay the allocation */ + if (!native_attachment_mask_test(attachment_mask, att)) + continue; - ptex = ksurf->textures[natt]; + ptex = ksurf->textures[att]; if (!ptex) { ptex = screen->texture_create(screen, &templ); - ksurf->textures[natt] = ptex; + ksurf->textures[att] = ptex; } - if (textures) - pipe_texture_reference(&textures[i], ptex); + if (textures) { + textures[att] = NULL; + pipe_texture_reference(&textures[att], ptex); + } } if (seq_num) @@ -113,7 +112,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) if (!fb->texture) { /* make sure the texture has been allocated */ - kms_surface_validate(&ksurf->base, &natt, 1, NULL, NULL, NULL, NULL); + kms_surface_validate(&ksurf->base, 1 << natt, NULL, NULL, NULL, NULL); if (!ksurf->textures[natt]) return FALSE; @@ -821,6 +820,18 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api) return &kdpy->base; } +struct native_probe * +native_create_probe(EGLNativeDisplayType dpy) +{ + return NULL; +} + +enum native_probe_result +native_get_probe_result(struct native_probe *nprobe) +{ + return NATIVE_PROBE_UNKNOWN; +} + /* the api is destroyed with the native display */ static struct drm_api *drm_api; diff --git a/src/gallium/state_trackers/egl_g3d/kms/native_kms.h b/src/gallium/state_trackers/egl/kms/native_kms.h index 095186e3cf..095186e3cf 100644 --- a/src/gallium/state_trackers/egl_g3d/kms/native_kms.h +++ b/src/gallium/state_trackers/egl/kms/native_kms.h diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index f497d8c1c7..07f82d878c 100644 --- a/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -134,22 +134,18 @@ dri2_surface_swap_buffers(struct native_surface *nsurf) } static boolean -dri2_surface_validate(struct native_surface *nsurf, - const enum native_attachment *natts, - unsigned num_natts, - unsigned int *seq_num, - struct pipe_texture **textures, - int *width, int *height) +dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, + unsigned int *seq_num, struct pipe_texture **textures, + int *width, int *height) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS]; - EGLint texture_indices[NUM_NATIVE_ATTACHMENTS]; struct pipe_texture templ; struct x11_drawable_buffer *xbufs; - int num_ins, num_outs, i; + int num_ins, num_outs, att, i; - if (num_natts) { + if (attachment_mask) { memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; templ.last_level = 0; @@ -160,24 +156,27 @@ dri2_surface_validate(struct native_surface *nsurf, templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; if (textures) - memset(textures, 0, sizeof(*textures) * num_natts); + memset(textures, 0, sizeof(*textures) * NUM_NATIVE_ATTACHMENTS); } /* create textures for pbuffer */ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) { struct pipe_screen *screen = dri2dpy->base.screen; - for (i = 0; i < num_natts; i++) { - enum native_attachment natt = natts[i]; - struct pipe_texture *ptex = dri2surf->pbuffer_textures[natt]; + for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { + struct pipe_texture *ptex = dri2surf->pbuffer_textures[att]; + + /* delay the allocation */ + if (!native_attachment_mask_test(attachment_mask, att)) + continue; if (!ptex) { ptex = screen->texture_create(screen, &templ); - dri2surf->pbuffer_textures[natt] = ptex; + dri2surf->pbuffer_textures[att] = ptex; } if (textures) - pipe_texture_reference(&textures[i], ptex); + pipe_texture_reference(&textures[att], ptex); } if (seq_num) @@ -190,34 +189,34 @@ dri2_surface_validate(struct native_surface *nsurf, return TRUE; } - for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) - texture_indices[i] = -1; - /* prepare the attachments */ - num_ins = num_natts; - for (i = 0; i < num_natts; i++) { - unsigned int dri2att; + num_ins = 0; + for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { + if (native_attachment_mask_test(attachment_mask, att)) { + unsigned int dri2att; + + switch (att) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + dri2att = DRI2BufferFrontLeft; + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + dri2att = DRI2BufferBackLeft; + break; + case NATIVE_ATTACHMENT_FRONT_RIGHT: + dri2att = DRI2BufferFrontRight; + break; + case NATIVE_ATTACHMENT_BACK_RIGHT: + dri2att = DRI2BufferBackRight; + break; + default: + assert(0); + dri2att = 0; + break; + } - switch (natts[i]) { - case NATIVE_ATTACHMENT_FRONT_LEFT: - dri2att = DRI2BufferFrontLeft; - break; - case NATIVE_ATTACHMENT_BACK_LEFT: - dri2att = DRI2BufferBackLeft; - break; - case NATIVE_ATTACHMENT_FRONT_RIGHT: - dri2att = DRI2BufferFrontRight; - break; - case NATIVE_ATTACHMENT_BACK_RIGHT: - dri2att = DRI2BufferBackRight; - break; - default: - assert(0); - dri2att = 0; - break; + dri2atts[num_ins] = dri2att; + num_ins++; } - dri2atts[i] = dri2att; - texture_indices[natts[i]] = i; } dri2surf->have_back = FALSE; @@ -266,13 +265,13 @@ dri2_surface_validate(struct native_surface *nsurf, break; } - if (!desc || texture_indices[natt] < 0 || - (textures && textures[texture_indices[natt]])) { + if (!desc || !native_attachment_mask_test(attachment_mask, natt) || + (textures && textures[natt])) { if (!desc) _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment); - else if (texture_indices[natt] < 0) + else if (!native_attachment_mask_test(attachment_mask, natt)) _eglLog(_EGL_WARNING, "unexpected buffer %d", xbuf->attachment); - else if (textures && textures[texture_indices[natt]]) + else _eglLog(_EGL_WARNING, "both real and fake front buffers are listed"); continue; } @@ -284,7 +283,7 @@ dri2_surface_validate(struct native_surface *nsurf, desc, xbuf->pitch, xbuf->name); if (ptex) { /* the caller owns the textures */ - textures[texture_indices[natt]] = ptex; + textures[natt] = ptex; } } } @@ -589,6 +588,21 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs) return configs; } +static boolean +dri2_display_is_pixmap_supported(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + struct dri2_display *dri2dpy = dri2_display(ndpy); + uint depth, nconf_depth; + + depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); + nconf_depth = util_format_get_blocksizebits(nconf->color_format); + + /* simple depth match for now */ + return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth)); +} + static void dri2_display_destroy(struct native_display *ndpy) { @@ -681,6 +695,7 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) dri2dpy->base.destroy = dri2_display_destroy; dri2dpy->base.get_configs = dri2_display_get_configs; + dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported; dri2dpy->base.create_context = dri2_display_create_context; dri2dpy->base.create_window_surface = dri2_display_create_window_surface; dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface; diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index 583ce3d329..dd3c9f8b6a 100644 --- a/src/gallium/state_trackers/egl_g3d/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -24,13 +24,90 @@ #include <string.h> #include "util/u_debug.h" +#include "util/u_memory.h" #include "state_tracker/drm_api.h" #include "egllog.h" #include "native_x11.h" +#include "x11_screen.h" + +#define X11_PROBE_MAGIC 0x11980BE /* "X11PROBE" */ static struct drm_api *api; +static void +x11_probe_destroy(struct native_probe *nprobe) +{ + if (nprobe->data) + free(nprobe->data); + free(nprobe); +} + +struct native_probe * +native_create_probe(EGLNativeDisplayType dpy) +{ + struct native_probe *nprobe; + struct x11_screen *xscr; + int scr; + const char *driver_name = NULL; + Display *xdpy; + + nprobe = CALLOC_STRUCT(native_probe); + if (!nprobe) + return NULL; + + xdpy = dpy; + if (!xdpy) { + xdpy = XOpenDisplay(NULL); + if (!xdpy) { + free(nprobe); + return NULL; + } + } + + scr = DefaultScreen(xdpy); + xscr = x11_screen_create(xdpy, scr); + if (xscr) { + if (x11_screen_support(xscr, X11_SCREEN_EXTENSION_DRI2)) { + driver_name = x11_screen_probe_dri2(xscr); + if (driver_name) + nprobe->data = strdup(driver_name); + } + + x11_screen_destroy(xscr); + } + + if (xdpy != dpy) + XCloseDisplay(xdpy); + + nprobe->magic = X11_PROBE_MAGIC; + nprobe->display = dpy; + + nprobe->destroy = x11_probe_destroy; + + return nprobe; +} + +enum native_probe_result +native_get_probe_result(struct native_probe *nprobe) +{ + if (!nprobe || nprobe->magic != X11_PROBE_MAGIC) + return NATIVE_PROBE_UNKNOWN; + + if (!api) + api = drm_api_create(); + + /* this is a software driver */ + if (!api) + return NATIVE_PROBE_SUPPORTED; + + /* the display does not support DRI2 or the driver mismatches */ + if (!nprobe->data || strcmp(api->name, (const char *) nprobe->data) != 0) + return NATIVE_PROBE_FALLBACK; + + return NATIVE_PROBE_EXACT; +} + const char * native_get_name(void) { diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h index 622ddac5df..622ddac5df 100644 --- a/src/gallium/state_trackers/egl_g3d/x11/native_x11.h +++ b/src/gallium/state_trackers/egl/x11/native_x11.h diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index 24a50df7a0..dfa8df2223 100644 --- a/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -66,7 +66,6 @@ struct ximage_buffer { XImage *ximage; struct pipe_texture *texture; - struct pipe_transfer *transfer; XShmSegmentInfo *shm_info; boolean xshm_attached; }; @@ -115,12 +114,7 @@ ximage_surface_free_buffer(struct native_surface *nsurf, { struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; - struct pipe_screen *screen = xsurf->xdpy->base.screen; - if (xbuf->transfer) { - screen->tex_transfer_destroy(xbuf->transfer); - xbuf->transfer = NULL; - } pipe_texture_reference(&xbuf->texture, NULL); if (xbuf->shm_info) { @@ -193,13 +187,6 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, xbuf->texture = screen->texture_create(screen, &templ); } - if (xbuf->texture) { - xbuf->transfer = screen->get_tex_transfer(screen, xbuf->texture, - 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height); - if (!xbuf->transfer) - pipe_texture_reference(&xbuf->texture, NULL); - } - /* clean up the buffer if allocation failed */ if (!xbuf->texture) ximage_surface_free_buffer(&xsurf->base, which); @@ -214,13 +201,25 @@ ximage_surface_draw_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; struct pipe_screen *screen = xsurf->xdpy->base.screen; + struct pipe_transfer *transfer; if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) return TRUE; assert(xsurf->drawable && xbuf->ximage && xbuf->texture); - xbuf->ximage->data = screen->transfer_map(screen, xbuf->transfer); + transfer = screen->get_tex_transfer(screen, xbuf->texture, + 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height); + if (!transfer) + return FALSE; + + xbuf->ximage->bytes_per_line = transfer->stride; + xbuf->ximage->data = screen->transfer_map(screen, transfer); + if (!xbuf->ximage->data) { + screen->tex_transfer_destroy(transfer); + return FALSE; + } + if (xbuf->shm_info) XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, @@ -230,7 +229,13 @@ ximage_surface_draw_buffer(struct native_surface *nsurf, xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height); xbuf->ximage->data = NULL; - screen->transfer_unmap(screen, xbuf->transfer); + screen->transfer_unmap(screen, transfer); + + /* + * softpipe allows the pipe transfer to be re-used, but we don't want to + * rely on that behavior. + */ + screen->tex_transfer_destroy(transfer); XSync(xsurf->xdpy->dpy, FALSE); @@ -289,27 +294,21 @@ ximage_surface_update_geometry(struct native_surface *nsurf) } static boolean -ximage_surface_validate(struct native_surface *nsurf, - const enum native_attachment *natts, - unsigned num_natts, - unsigned int *seq_num, - struct pipe_texture **textures, - int *width, int *height) +ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, + unsigned int *seq_num, struct pipe_texture **textures, + int *width, int *height) { struct ximage_surface *xsurf = ximage_surface(nsurf); - boolean new_buffers = FALSE, error = FALSE; - unsigned i; + boolean new_buffers = FALSE; + int att; ximage_surface_update_geometry(&xsurf->base); - if (textures) - memset(textures, 0, sizeof(*textures) * num_natts); - - for (i = 0; i < num_natts; i++) { - enum native_attachment natt = natts[i]; - struct ximage_buffer *xbuf = &xsurf->buffers[natt]; + for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { + struct ximage_buffer *xbuf = &xsurf->buffers[att]; - if (!xbuf) + /* delay the allocation */ + if (!native_attachment_mask_test(attachment_mask, att)) continue; /* reallocate the texture */ @@ -317,29 +316,19 @@ ximage_surface_validate(struct native_surface *nsurf, xsurf->width != xbuf->texture->width0 || xsurf->height != xbuf->texture->height0) { new_buffers = TRUE; - if (ximage_surface_alloc_buffer(&xsurf->base, natt)) { + if (ximage_surface_alloc_buffer(&xsurf->base, att)) { /* update ximage */ if (xbuf->ximage) { - xbuf->ximage->width = xbuf->transfer->width; - xbuf->ximage->height = xbuf->transfer->height; - xbuf->ximage->bytes_per_line = xbuf->transfer->stride; + xbuf->ximage->width = xsurf->width; + xbuf->ximage->height = xsurf->height; } } } - /* allocation failed */ - if (!xbuf->texture) { - unsigned j; - for (j = 0; j < i; j++) - pipe_texture_reference(&textures[j], NULL); - for (j = i; j < num_natts; j++) - textures[j] = NULL; - error = TRUE; - break; + if (textures) { + textures[att] = NULL; + pipe_texture_reference(&textures[att], xbuf->texture); } - - if (textures) - pipe_texture_reference(&textures[i], xbuf->texture); } /* increase the sequence number so that caller knows */ @@ -353,7 +342,7 @@ ximage_surface_validate(struct native_surface *nsurf, if (height) *height = xsurf->height; - return !error; + return TRUE; } static void @@ -615,6 +604,34 @@ ximage_display_get_configs(struct native_display *ndpy, int *num_configs) return configs; } +static boolean +ximage_display_is_pixmap_supported(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + struct ximage_display *xdpy = ximage_display(ndpy); + enum pipe_format fmt; + uint depth; + + depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix); + switch (depth) { + case 32: + fmt = PIPE_FORMAT_A8R8G8B8_UNORM; + break; + case 24: + fmt = PIPE_FORMAT_X8R8G8B8_UNORM; + break; + case 16: + fmt = PIPE_FORMAT_R5G6B5_UNORM; + break; + default: + fmt = PIPE_FORMAT_NONE; + break; + } + + return (fmt == nconf->color_format); +} + static void ximage_display_destroy(struct native_display *ndpy) { @@ -667,6 +684,7 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm) xdpy->base.destroy = ximage_display_destroy; xdpy->base.get_configs = ximage_display_get_configs; + xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported; xdpy->base.create_context = ximage_display_create_context; xdpy->base.create_window_surface = ximage_display_create_window_surface; xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface; diff --git a/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c b/src/gallium/state_trackers/egl/x11/sw_winsys.c index 6ee3ede38c..6ee3ede38c 100644 --- a/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c +++ b/src/gallium/state_trackers/egl/x11/sw_winsys.c diff --git a/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.h b/src/gallium/state_trackers/egl/x11/sw_winsys.h index f96c5a14b0..f96c5a14b0 100644 --- a/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.h +++ b/src/gallium/state_trackers/egl/x11/sw_winsys.h diff --git a/src/gallium/state_trackers/egl_g3d/x11/x11_screen.c b/src/gallium/state_trackers/egl/x11/x11_screen.c index 1e98943242..76ce45ee57 100644 --- a/src/gallium/state_trackers/egl_g3d/x11/x11_screen.c +++ b/src/gallium/state_trackers/egl/x11/x11_screen.c @@ -30,6 +30,7 @@ #include <X11/extensions/XShm.h> #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_format.h" #include "xf86drm.h" #include "egllog.h" @@ -41,6 +42,10 @@ struct x11_screen { Display *dpy; int number; + /* + * This is used to fetch GLX visuals/fbconfigs. It uses code from egl_xdri. + * It might be better to rewrite the part in Xlib or XCB. + */ __GLXdisplayPrivate *glx_dpy; int dri_major, dri_minor; @@ -50,6 +55,10 @@ struct x11_screen { XVisualInfo *visuals; int num_visuals; + + /* cached values for x11_drawable_get_depth */ + Drawable last_drawable; + unsigned int last_depth; }; @@ -88,8 +97,8 @@ x11_screen_destroy(struct x11_screen *xscr) if (xscr->dri_device) Xfree(xscr->dri_device); - if (xscr->glx_dpy) - __glXRelease(xscr->glx_dpy); + /* xscr->glx_dpy will be destroyed with the X display */ + if (xscr->visuals) XFree(xscr->visuals); free(xscr); @@ -245,6 +254,22 @@ x11_screen_is_driver_equal(struct x11_screen *xscr, const char *driver) } /** + * Probe the screen for the DRI2 driver name. + */ +const char * +x11_screen_probe_dri2(struct x11_screen *xscr) +{ + /* get the driver name and the device name */ + if (!xscr->dri_driver) { + if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number), + &xscr->dri_driver, &xscr->dri_device)) + xscr->dri_driver = xscr->dri_device = NULL; + } + + return xscr->dri_driver; +} + +/** * Enable DRI2 and returns the file descriptor of the DRM device. The file * descriptor will be closed automatically when the screen is destoryed. */ @@ -256,13 +281,8 @@ x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver) drm_magic_t magic; /* get the driver name and the device name first */ - if (!xscr->dri_driver) { - if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number), - &xscr->dri_driver, &xscr->dri_device)) { - xscr->dri_driver = xscr->dri_device = NULL; - return -1; - } - } + if (!x11_screen_probe_dri2(xscr)) + return -1; if (!x11_screen_is_driver_equal(xscr, driver)) { _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s", @@ -351,6 +371,37 @@ x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable, } /** + * Return the depth of a drawable. + * + * Unlike other drawable functions, the drawable needs not be a DRI2 drawable. + */ +uint +x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable) +{ + unsigned int depth; + + if (drawable != xscr->last_drawable) { + Window root; + int x, y; + unsigned int w, h, border; + Status ok; + + ok = XGetGeometry(xscr->dpy, drawable, &root, + &x, &y, &w, &h, &border, &depth); + if (!ok) + depth = 0; + + xscr->last_drawable = drawable; + xscr->last_depth = depth; + } + else { + depth = xscr->last_depth; + } + + return depth; +} + +/** * Create a mode list of the given size. */ __GLcontextModes * diff --git a/src/gallium/state_trackers/egl_g3d/x11/x11_screen.h b/src/gallium/state_trackers/egl/x11/x11_screen.h index 86e8e0501a..5432858ac3 100644 --- a/src/gallium/state_trackers/egl_g3d/x11/x11_screen.h +++ b/src/gallium/state_trackers/egl/x11/x11_screen.h @@ -70,6 +70,9 @@ x11_screen_get_glx_configs(struct x11_screen *xscr); const __GLcontextModes * x11_screen_get_glx_visuals(struct x11_screen *xscr); +const char * +x11_screen_probe_dri2(struct x11_screen *xscr); + int x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver); @@ -96,4 +99,7 @@ x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable, int *width, int *height, unsigned int *attachments, boolean with_format, int num_ins, int *num_outs); +uint +x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable); + #endif /* _X11_SCREEN_H_ */ diff --git a/src/gallium/state_trackers/egl_g3d/Makefile b/src/gallium/state_trackers/egl_g3d/Makefile deleted file mode 100644 index 213eb3e815..0000000000 --- a/src/gallium/state_trackers/egl_g3d/Makefile +++ /dev/null @@ -1,72 +0,0 @@ -TOP = ../../../.. -include $(TOP)/configs/current - -common_INCLUDES = \ - -I. \ - -I$(TOP)/src/gallium/include \ - -I$(TOP)/src/gallium/auxiliary \ - -I$(TOP)/src/egl/main \ - -I$(TOP)/include - -common_SOURCES = $(wildcard common/*.c) -common_OBJECTS = $(common_SOURCES:.c=.o) - - -x11_INCLUDES = \ - -I$(TOP)/src/gallium/drivers \ - -I$(TOP)/src/glx/x11 \ - -I$(TOP)/src/mesa \ - $(shell pkg-config --cflags-only-I libdrm) - -x11_SOURCES = $(wildcard x11/*.c) $(TOP)/src/glx/x11/dri2.c -x11_OBJECTS = $(x11_SOURCES:.c=.o) - - -kms_INCLUDES = $(shell pkg-config --cflags-only-I libdrm) -kms_SOURCES = $(wildcard kms/*.c) -kms_OBJECTS = $(kms_SOURCES:.c=.o) - - -ALL_INCLUDES = $(common_INCLUDES) $(x11_INCLUDES) $(kms_INCLUDES) -ALL_SOURCES = $(common_SOURCES) $(x11_SOURCES) $(kms_SOURCES) -ALL_OBJECTS = $(common_OBJECTS) $(x11_OBJECTS) $(kms_OBJECTS) - -##### TARGETS ##### - -EGL_DISPLAYS_MODS = $(foreach dpy, $(EGL_DISPLAYS), libegl$(dpy).a) - -default: depend $(EGL_DISPLAYS_MODS) - - -libeglx11.a: $(x11_OBJECTS) $(common_OBJECTS) Makefile - $(MKLIB) -o eglx11 -static $(x11_OBJECTS) $(common_OBJECTS) - -libeglkms.a: $(kms_OBJECTS) $(common_OBJECTS) Makefile - $(MKLIB) -o eglkms -static $(kms_OBJECTS) $(common_OBJECTS) - -depend: - rm -f depend - touch depend - $(MKDEP) $(MKDEP_OPTIONS) $(ALL_INCLUDES) $(ALL_SOURCES) 2> /dev/null - -clean: - rm -f $(ALL_OBJECTS) - rm -f $(EGL_DISPLAYS_MODS) - rm -f depend depend.bak - -# Dummy target -install: - @echo -n "" - -##### RULES ##### - -$(common_OBJECTS): %.o: %.c - $(CC) -c $(common_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ - -$(x11_OBJECTS): %.o: %.c - $(CC) -c $(common_INCLUDES) $(x11_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ - -$(kms_OBJECTS): %.o: %.c - $(CC) -c $(common_INCLUDES) $(kms_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ - -sinclude depend diff --git a/src/gallium/state_trackers/egl_g3d/x11/glxinit.c b/src/gallium/state_trackers/egl_g3d/x11/glxinit.c deleted file mode 100644 index c955a908b9..0000000000 --- a/src/gallium/state_trackers/egl_g3d/x11/glxinit.c +++ /dev/null @@ -1,573 +0,0 @@ -/** - * GLX initialization. Code based on glxext.c, glx_query.c, and - * glcontextmodes.c under src/glx/x11/. The major difference is that no DRI - * related code here. - * - */ - -#include <assert.h> -#include <X11/Xlib.h> -#include <X11/Xproto.h> -#include <X11/extensions/Xext.h> -#include <X11/extensions/extutil.h> -#include <sys/time.h> - -#include "x11_screen.h" -#include "glxinit.h" - -typedef struct GLXGenericGetString -{ - CARD8 reqType; - CARD8 glxCode; - CARD16 length B16; - CARD32 for_whom B32; - CARD32 name B32; -} xGLXGenericGetStringReq; - -#define sz_xGLXGenericGetStringReq 12 -#define X_GLXGenericGetString 0 - -/* Extension required boiler plate */ - -static char *__glXExtensionName = GLX_EXTENSION_NAME; -static XExtensionInfo *__glXExtensionInfo = NULL; - -static /* const */ XExtensionHooks __glXExtensionHooks = { NULL }; -static -XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo, - __glXExtensionName, &__glXExtensionHooks, - __GLX_NUMBER_EVENTS, NULL) - -static GLint -_gl_convert_from_x_visual_type(int visualType) -{ -#define NUM_VISUAL_TYPES 6 - static const int glx_visual_types[NUM_VISUAL_TYPES] = { - GLX_STATIC_GRAY, GLX_GRAY_SCALE, - GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, - GLX_TRUE_COLOR, GLX_DIRECT_COLOR - }; - - return ((unsigned) visualType < NUM_VISUAL_TYPES) - ? glx_visual_types[visualType] : GLX_NONE; -} - -_X_HIDDEN char * -__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name) -{ - xGLXGenericGetStringReq *req; - xGLXSingleReply reply; - int length; - int numbytes; - char *buf; - CARD32 for_whom = screen; - CARD32 glxCode = X_GLXQueryServerString; - - - LockDisplay(dpy); - - - /* All of the GLX protocol requests for getting a string from the server - * look the same. The exact meaning of the for_whom field is usually - * either the screen number (for glXQueryServerString) or the context tag - * (for GLXSingle). - */ - - GetReq(GLXGenericGetString, req); - req->reqType = opcode; - req->glxCode = glxCode; - req->for_whom = for_whom; - req->name = name; - - _XReply(dpy, (xReply *) & reply, 0, False); - - length = reply.length * 4; - numbytes = reply.size; - - buf = (char *) Xmalloc(numbytes); - if (buf != NULL) { - _XRead(dpy, buf, numbytes); - length -= numbytes; - } - - _XEatData(dpy, length); - - UnlockDisplay(dpy); - SyncHandle(); - - return buf; -} - -/************************************************************************/ -/* -** Free the per screen configs data as well as the array of -** __glXScreenConfigs. -*/ -static void -FreeScreenConfigs(__GLXdisplayPrivate * priv) -{ - __GLXscreenConfigs *psc; - GLint i, screens; - - /* Free screen configuration information */ - psc = priv->screenConfigs; - screens = ScreenCount(priv->dpy); - for (i = 0; i < screens; i++, psc++) { - if (psc->configs) { - x11_context_modes_destroy(psc->configs); - psc->configs = NULL; /* NOTE: just for paranoia */ - } - if (psc->visuals) { - x11_context_modes_destroy(psc->visuals); - psc->visuals = NULL; /* NOTE: just for paranoia */ - } - Xfree((char *) psc->serverGLXexts); - } - XFree((char *) priv->screenConfigs); - priv->screenConfigs = NULL; -} - -/************************************************************************/ - -/* -** Query the version of the GLX extension. This procedure works even if -** the client extension is not completely set up. -*/ -static Bool -QueryVersion(Display * dpy, int opcode, int *major, int *minor) -{ - xGLXQueryVersionReq *req; - xGLXQueryVersionReply reply; - - /* Send the glXQueryVersion request */ - LockDisplay(dpy); - GetReq(GLXQueryVersion, req); - req->reqType = opcode; - req->glxCode = X_GLXQueryVersion; - req->majorVersion = GLX_MAJOR_VERSION; - req->minorVersion = GLX_MINOR_VERSION; - _XReply(dpy, (xReply *) & reply, 0, False); - UnlockDisplay(dpy); - SyncHandle(); - - if (reply.majorVersion != GLX_MAJOR_VERSION) { - /* - ** The server does not support the same major release as this - ** client. - */ - return GL_FALSE; - } - *major = reply.majorVersion; - *minor = min(reply.minorVersion, GLX_MINOR_VERSION); - return GL_TRUE; -} - -_X_HIDDEN void -__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, - const INT32 * bp, Bool tagged_only, - Bool fbconfig_style_tags) -{ - int i; - - if (!tagged_only) { - /* Copy in the first set of properties */ - config->visualID = *bp++; - - config->visualType = _gl_convert_from_x_visual_type(*bp++); - - config->rgbMode = *bp++; - - config->redBits = *bp++; - config->greenBits = *bp++; - config->blueBits = *bp++; - config->alphaBits = *bp++; - config->accumRedBits = *bp++; - config->accumGreenBits = *bp++; - config->accumBlueBits = *bp++; - config->accumAlphaBits = *bp++; - - config->doubleBufferMode = *bp++; - config->stereoMode = *bp++; - - config->rgbBits = *bp++; - config->depthBits = *bp++; - config->stencilBits = *bp++; - config->numAuxBuffers = *bp++; - config->level = *bp++; - - count -= __GLX_MIN_CONFIG_PROPS; - } - - /* - ** Additional properties may be in a list at the end - ** of the reply. They are in pairs of property type - ** and property value. - */ - -#define FETCH_OR_SET(tag) \ - config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1 - - for (i = 0; i < count; i += 2) { - switch (*bp++) { - case GLX_RGBA: - FETCH_OR_SET(rgbMode); - break; - case GLX_BUFFER_SIZE: - config->rgbBits = *bp++; - break; - case GLX_LEVEL: - config->level = *bp++; - break; - case GLX_DOUBLEBUFFER: - FETCH_OR_SET(doubleBufferMode); - break; - case GLX_STEREO: - FETCH_OR_SET(stereoMode); - break; - case GLX_AUX_BUFFERS: - config->numAuxBuffers = *bp++; - break; - case GLX_RED_SIZE: - config->redBits = *bp++; - break; - case GLX_GREEN_SIZE: - config->greenBits = *bp++; - break; - case GLX_BLUE_SIZE: - config->blueBits = *bp++; - break; - case GLX_ALPHA_SIZE: - config->alphaBits = *bp++; - break; - case GLX_DEPTH_SIZE: - config->depthBits = *bp++; - break; - case GLX_STENCIL_SIZE: - config->stencilBits = *bp++; - break; - case GLX_ACCUM_RED_SIZE: - config->accumRedBits = *bp++; - break; - case GLX_ACCUM_GREEN_SIZE: - config->accumGreenBits = *bp++; - break; - case GLX_ACCUM_BLUE_SIZE: - config->accumBlueBits = *bp++; - break; - case GLX_ACCUM_ALPHA_SIZE: - config->accumAlphaBits = *bp++; - break; - case GLX_VISUAL_CAVEAT_EXT: - config->visualRating = *bp++; - break; - case GLX_X_VISUAL_TYPE: - config->visualType = *bp++; - break; - case GLX_TRANSPARENT_TYPE: - config->transparentPixel = *bp++; - break; - case GLX_TRANSPARENT_INDEX_VALUE: - config->transparentIndex = *bp++; - break; - case GLX_TRANSPARENT_RED_VALUE: - config->transparentRed = *bp++; - break; - case GLX_TRANSPARENT_GREEN_VALUE: - config->transparentGreen = *bp++; - break; - case GLX_TRANSPARENT_BLUE_VALUE: - config->transparentBlue = *bp++; - break; - case GLX_TRANSPARENT_ALPHA_VALUE: - config->transparentAlpha = *bp++; - break; - case GLX_VISUAL_ID: - config->visualID = *bp++; - break; - case GLX_DRAWABLE_TYPE: - config->drawableType = *bp++; - break; - case GLX_RENDER_TYPE: - config->renderType = *bp++; - break; - case GLX_X_RENDERABLE: - config->xRenderable = *bp++; - break; - case GLX_FBCONFIG_ID: - config->fbconfigID = *bp++; - break; - case GLX_MAX_PBUFFER_WIDTH: - config->maxPbufferWidth = *bp++; - break; - case GLX_MAX_PBUFFER_HEIGHT: - config->maxPbufferHeight = *bp++; - break; - case GLX_MAX_PBUFFER_PIXELS: - config->maxPbufferPixels = *bp++; - break; - case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: - config->optimalPbufferWidth = *bp++; - break; - case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: - config->optimalPbufferHeight = *bp++; - break; - case GLX_VISUAL_SELECT_GROUP_SGIX: - config->visualSelectGroup = *bp++; - break; - case GLX_SWAP_METHOD_OML: - config->swapMethod = *bp++; - break; - case GLX_SAMPLE_BUFFERS_SGIS: - config->sampleBuffers = *bp++; - break; - case GLX_SAMPLES_SGIS: - config->samples = *bp++; - break; - case GLX_BIND_TO_TEXTURE_RGB_EXT: - config->bindToTextureRgb = *bp++; - break; - case GLX_BIND_TO_TEXTURE_RGBA_EXT: - config->bindToTextureRgba = *bp++; - break; - case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: - config->bindToMipmapTexture = *bp++; - break; - case GLX_BIND_TO_TEXTURE_TARGETS_EXT: - config->bindToTextureTargets = *bp++; - break; - case GLX_Y_INVERTED_EXT: - config->yInverted = *bp++; - break; - case None: - i = count; - break; - default: - break; - } - } - - config->renderType = - (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; - - config->haveAccumBuffer = ((config->accumRedBits + - config->accumGreenBits + - config->accumBlueBits + - config->accumAlphaBits) > 0); - config->haveDepthBuffer = (config->depthBits > 0); - config->haveStencilBuffer = (config->stencilBits > 0); -} - -static __GLcontextModes * -createConfigsFromProperties(Display * dpy, int nvisuals, int nprops, - int screen, GLboolean tagged_only) -{ - INT32 buf[__GLX_TOTAL_CONFIG], *props; - unsigned prop_size; - __GLcontextModes *modes, *m; - int i; - - if (nprops == 0) - return NULL; - - /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */ - - /* Check number of properties */ - if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS) - return NULL; - - /* Allocate memory for our config structure */ - modes = x11_context_modes_create(nvisuals); - if (!modes) - return NULL; - - prop_size = nprops * __GLX_SIZE_INT32; - if (prop_size <= sizeof(buf)) - props = buf; - else - props = Xmalloc(prop_size); - - /* Read each config structure and convert it into our format */ - m = modes; - for (i = 0; i < nvisuals; i++) { - _XRead(dpy, (char *) props, prop_size); - /* Older X servers don't send this so we default it here. */ - m->drawableType = GLX_WINDOW_BIT; - __glXInitializeVisualConfigFromTags(m, nprops, props, - tagged_only, GL_TRUE); - m->screen = screen; - m = m->next; - } - - if (props != buf) - Xfree(props); - - return modes; -} - -static GLboolean -getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) -{ - xGLXGetVisualConfigsReq *req; - __GLXscreenConfigs *psc; - xGLXGetVisualConfigsReply reply; - - LockDisplay(dpy); - - psc = priv->screenConfigs + screen; - psc->visuals = NULL; - GetReq(GLXGetVisualConfigs, req); - req->reqType = priv->majorOpcode; - req->glxCode = X_GLXGetVisualConfigs; - req->screen = screen; - - if (!_XReply(dpy, (xReply *) & reply, 0, False)) - goto out; - - psc->visuals = createConfigsFromProperties(dpy, - reply.numVisuals, - reply.numProps, - screen, GL_FALSE); - - out: - UnlockDisplay(dpy); - return psc->visuals != NULL; -} - -static GLboolean -getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) -{ - xGLXGetFBConfigsReq *fb_req; - xGLXGetFBConfigsSGIXReq *sgi_req; - xGLXVendorPrivateWithReplyReq *vpreq; - xGLXGetFBConfigsReply reply; - __GLXscreenConfigs *psc; - - psc = priv->screenConfigs + screen; - psc->serverGLXexts = - __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); - - LockDisplay(dpy); - - psc->configs = NULL; - if (atof(priv->serverGLXversion) >= 1.3) { - GetReq(GLXGetFBConfigs, fb_req); - fb_req->reqType = priv->majorOpcode; - fb_req->glxCode = X_GLXGetFBConfigs; - fb_req->screen = screen; - } - else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { - GetReqExtra(GLXVendorPrivateWithReply, - sz_xGLXGetFBConfigsSGIXReq + - sz_xGLXVendorPrivateWithReplyReq, vpreq); - sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; - sgi_req->reqType = priv->majorOpcode; - sgi_req->glxCode = X_GLXVendorPrivateWithReply; - sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; - sgi_req->screen = screen; - } - else - goto out; - - if (!_XReply(dpy, (xReply *) & reply, 0, False)) - goto out; - - psc->configs = createConfigsFromProperties(dpy, - reply.numFBConfigs, - reply.numAttribs * 2, - screen, GL_TRUE); - - out: - UnlockDisplay(dpy); - return psc->configs != NULL; -} - -static GLboolean -AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) -{ - __GLXscreenConfigs *psc; - GLint i, screens; - - /* - ** First allocate memory for the array of per screen configs. - */ - screens = ScreenCount(dpy); - psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs)); - if (!psc) { - return GL_FALSE; - } - memset(psc, 0, screens * sizeof(__GLXscreenConfigs)); - priv->screenConfigs = psc; - - priv->serverGLXversion = - __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); - if (priv->serverGLXversion == NULL) { - FreeScreenConfigs(priv); - return GL_FALSE; - } - - for (i = 0; i < screens; i++, psc++) { - getFBConfigs(dpy, priv, i); - getVisualConfigs(dpy, priv, i); - psc->scr = i; - psc->dpy = dpy; - } - - SyncHandle(); - - return GL_TRUE; -} - -_X_HIDDEN void -__glXRelease(__GLXdisplayPrivate *dpyPriv) -{ - FreeScreenConfigs(dpyPriv); - - if (dpyPriv->serverGLXvendor) { - Xfree((char *) dpyPriv->serverGLXvendor); - dpyPriv->serverGLXvendor = NULL; - } - if (dpyPriv->serverGLXversion) { - Xfree((char *) dpyPriv->serverGLXversion); - dpyPriv->serverGLXversion = NULL; - } - - Xfree(dpyPriv); -} - -_X_HIDDEN __GLXdisplayPrivate * -__glXInitialize(Display * dpy) -{ - XExtDisplayInfo *info = __glXFindDisplay(dpy); - __GLXdisplayPrivate *dpyPriv; - int major, minor; - - if (!XextHasExtension(info)) - return NULL; - - /* See if the versions are compatible */ - if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) - return NULL; - - dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate)); - if (!dpyPriv) - return NULL; - - /* - ** Init the display private and then read in the screen config - ** structures from the server. - */ - dpyPriv->majorOpcode = info->codes->major_opcode; - dpyPriv->majorVersion = major; - dpyPriv->minorVersion = minor; - dpyPriv->dpy = dpy; - - dpyPriv->serverGLXvendor = NULL; - dpyPriv->serverGLXversion = NULL; - - if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { - Xfree(dpyPriv); - return NULL; - } - - return dpyPriv; -} diff --git a/src/gallium/state_trackers/egl_g3d/x11/glxinit.h b/src/gallium/state_trackers/egl_g3d/x11/glxinit.h deleted file mode 100644 index 515a825222..0000000000 --- a/src/gallium/state_trackers/egl_g3d/x11/glxinit.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef GLXINIT_INCLUDED -#define GLXINIT_INCLUDED - -#include <X11/Xlib.h> - -#ifndef GLX_DIRECT_RENDERING -#define GLX_DIRECT_RENDERING -#endif -#include "glxclient.h" - -extern void -__glXRelease(__GLXdisplayPrivate *dpyPriv); - -#endif /* GLXINIT_INCLUDED */ diff --git a/src/gallium/state_trackers/es/Makefile b/src/gallium/state_trackers/es/Makefile new file mode 100644 index 0000000000..b036551271 --- /dev/null +++ b/src/gallium/state_trackers/es/Makefile @@ -0,0 +1,84 @@ +# src/gallium/state_trackers/es/Makefile + +# Build the ES 1/2 state tracker libraries +# This consists of core Mesa ES, plus GL/gallium state tracker. + +TOP = ../../../.. +include $(TOP)/configs/current + +GLES_1_VERSION_MAJOR = 1 +GLES_1_VERSION_MINOR = 1 +GLES_1_VERSION_PATCH = 0 + +GLES_2_VERSION_MAJOR = 2 +GLES_2_VERSION_MINOR = 0 +GLES_2_VERSION_PATCH = 0 + + +# Maybe move these into configs/default: +GLES_1_LIB = GLESv1_CM +GLES_1_LIB_NAME = lib$(GLES_1_LIB).so +GLES_2_LIB = GLESv2 +GLES_2_LIB_NAME = lib$(GLES_2_LIB).so + + +ES1_OBJECTS = st_es1.o +ES2_OBJECTS = st_es2.o + + +ES1_LIBS = \ + $(TOP)/src/mesa/es/libes1gallium.a \ + $(TOP)/src/mesa/es/libes1api.a + +ES2_LIBS = \ + $(TOP)/src/mesa/es/libes2gallium.a \ + $(TOP)/src/mesa/es/libes2api.a + +SYS_LIBS = -lm -pthread + + +INCLUDE_DIRS = \ + -I$(TOP)/src/gallium/include + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) $< -o $@ + + +# Default: make both GL ES 1.1 and GL ES 2.0 libraries +default: $(TOP)/$(LIB_DIR)/$(GLES_1_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLES_2_LIB_NAME) + +# Make the shared libs +$(TOP)/$(LIB_DIR)/$(GLES_1_LIB_NAME): $(ES1_OBJECTS) $(ES1_LIBS) $(GALLIUM_AUXILIARIES) + $(MKLIB) -o $(GLES_1_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + -major $(GLES_1_VERSION_MAJOR) \ + -minor $(GLES_1_VERSION_MINOR) \ + -patch $(GLES_1_VERSION_PATCH) \ + -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \ + $(ES1_OBJECTS) \ + -Wl,--whole-archive $(ES1_LIBS) -Wl,--no-whole-archive \ + $(GALLIUM_AUXILIARIES) $(SYS_LIBS) + +$(TOP)/$(LIB_DIR)/$(GLES_2_LIB_NAME): $(ES2_OBJECTS) $(ES1_LIBS) $(GALLIUM_AUXILIARIES) + $(MKLIB) -o $(GLES_2_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + -major $(GLES_2_VERSION_MAJOR) \ + -minor $(GLES_2_VERSION_MINOR) \ + -patch $(GLES_2_VERSION_PATCH) \ + -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \ + $(ES2_OBJECTS) \ + -Wl,--whole-archive $(ES2_LIBS) -Wl,--no-whole-archive \ + $(GALLIUM_AUXILIARIES) $(SYS_LIBS) + +install: default + $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/include/GLES + $(INSTALL) -m 644 $(TOP)/include/GLES/*.h $(DESTDIR)$(INSTALL_DIR)/include/GLES + $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/include/GLES2 + $(INSTALL) -m 644 $(TOP)/include/GLES2/*.h $(DESTDIR)$(INSTALL_DIR)/include/GLES2 + $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR) + $(MINSTALL) $(TOP)/$(LIB_DIR)/libGLESv1* $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR) + $(MINSTALL) $(TOP)/$(LIB_DIR)/libGLESv2* $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR) + +clean: + -rm -f *.o *~ + -rm -f $(TOP)/$(LIB_DIR)/$(GLES_1_LIB_NAME)* $(TOP)/$(LIB_DIR)/$(GLES_2_LIB_NAME)* + +depend: diff --git a/src/gallium/state_trackers/es/st_es1.c b/src/gallium/state_trackers/es/st_es1.c new file mode 100644 index 0000000000..25bc53b21e --- /dev/null +++ b/src/gallium/state_trackers/es/st_es1.c @@ -0,0 +1,3 @@ +#include "pipe/p_compiler.h" + +PUBLIC const int st_api_OpenGL_ES1 = 1; diff --git a/src/gallium/state_trackers/es/st_es2.c b/src/gallium/state_trackers/es/st_es2.c new file mode 100644 index 0000000000..171ea62b97 --- /dev/null +++ b/src/gallium/state_trackers/es/st_es2.c @@ -0,0 +1,3 @@ +#include "pipe/p_compiler.h" + +PUBLIC const int st_api_OpenGL_ES2 = 1; diff --git a/src/gallium/state_trackers/glx/xlib/glx_getproc.c b/src/gallium/state_trackers/glx/xlib/glx_getproc.c index 84d47b12ed..bd4a85caa0 100644 --- a/src/gallium/state_trackers/glx/xlib/glx_getproc.c +++ b/src/gallium/state_trackers/glx/xlib/glx_getproc.c @@ -193,7 +193,7 @@ _glxapi_get_proc_address(const char *funcName) } -__GLXextFuncPtr +PUBLIC __GLXextFuncPtr glXGetProcAddressARB(const GLubyte *procName) { __GLXextFuncPtr f; diff --git a/src/gallium/state_trackers/python/SConscript b/src/gallium/state_trackers/python/SConscript index 8498a90812..527e065cd9 100644 --- a/src/gallium/state_trackers/python/SConscript +++ b/src/gallium/state_trackers/python/SConscript @@ -21,6 +21,7 @@ if 'python' in env['statetrackers']: 'gdi32', 'user32', 'kernel32', + 'ws2_32', ]) else: env.Append(LIBS = [ diff --git a/src/gallium/state_trackers/python/samples/gs.py b/src/gallium/state_trackers/python/samples/gs.py index a07cf557f2..cd68abac9a 100644 --- a/src/gallium/state_trackers/python/samples/gs.py +++ b/src/gallium/state_trackers/python/samples/gs.py @@ -72,11 +72,11 @@ def test(dev): # disabled blending/masking blend = Blend() - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.colormask = PIPE_MASK_RGBA + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].colormask = PIPE_MASK_RGBA ctx.set_blend(blend) # depth/stencil/alpha diff --git a/src/gallium/state_trackers/python/samples/tri.py b/src/gallium/state_trackers/python/samples/tri.py index e5e168bdc8..f0b5e3dc98 100644 --- a/src/gallium/state_trackers/python/samples/tri.py +++ b/src/gallium/state_trackers/python/samples/tri.py @@ -72,11 +72,11 @@ def test(dev): # disabled blending/masking blend = Blend() - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.colormask = PIPE_MASK_RGBA + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].colormask = PIPE_MASK_RGBA ctx.set_blend(blend) # depth/stencil/alpha diff --git a/src/gallium/state_trackers/python/st_device.c b/src/gallium/state_trackers/python/st_device.c index d144af2447..e41125f6f9 100644 --- a/src/gallium/state_trackers/python/st_device.c +++ b/src/gallium/state_trackers/python/st_device.c @@ -180,11 +180,11 @@ st_context_create(struct st_device *st_dev) { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].colormask = PIPE_MASK_RGBA; cso_set_blend(st_ctx->cso, &blend); } diff --git a/src/gallium/state_trackers/python/st_softpipe_winsys.c b/src/gallium/state_trackers/python/st_softpipe_winsys.c index a3294e877a..dfe3e465f7 100644 --- a/src/gallium/state_trackers/python/st_softpipe_winsys.c +++ b/src/gallium/state_trackers/python/st_softpipe_winsys.c @@ -35,225 +35,10 @@ * @author Jose Fonseca */ - -#include "pipe/internal/p_winsys_screen.h"/* port to just p_screen */ -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "pipe/p_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" #include "softpipe/sp_winsys.h" #include "st_winsys.h" - -struct st_softpipe_buffer -{ - struct pipe_buffer base; - boolean userBuffer; /** Is this a user-space buffer? */ - void *data; - void *mapped; -}; - - -/** Cast wrapper */ -static INLINE struct st_softpipe_buffer * -st_softpipe_buffer( struct pipe_buffer *buf ) -{ - return (struct st_softpipe_buffer *)buf; -} - - -static void * -st_softpipe_buffer_map(struct pipe_winsys *winsys, - struct pipe_buffer *buf, - unsigned flags) -{ - struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); - st_softpipe_buf->mapped = st_softpipe_buf->data; - return st_softpipe_buf->mapped; -} - - -static void -st_softpipe_buffer_unmap(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); - st_softpipe_buf->mapped = NULL; -} - - -static void -st_softpipe_buffer_destroy(struct pipe_buffer *buf) -{ - struct st_softpipe_buffer *oldBuf = st_softpipe_buffer(buf); - - if (oldBuf->data) { - if (!oldBuf->userBuffer) - align_free(oldBuf->data); - - oldBuf->data = NULL; - } - - FREE(oldBuf); -} - - -static void -st_softpipe_flush_frontbuffer(struct pipe_winsys *winsys, - struct pipe_surface *surf, - void *context_private) -{ -} - - - -static const char * -st_softpipe_get_name(struct pipe_winsys *winsys) -{ - return "softpipe"; -} - - -static struct pipe_buffer * -st_softpipe_buffer_create(struct pipe_winsys *winsys, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct st_softpipe_buffer *buffer = CALLOC_STRUCT(st_softpipe_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - - buffer->data = align_malloc(size, alignment); - - return &buffer->base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -st_softpipe_user_buffer_create(struct pipe_winsys *winsys, - void *ptr, - unsigned bytes) -{ - struct st_softpipe_buffer *buffer; - - buffer = CALLOC_STRUCT(st_softpipe_buffer); - if(!buffer) - return NULL; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.size = bytes; - buffer->userBuffer = TRUE; - buffer->data = ptr; - - return &buffer->base; -} - - -static struct pipe_buffer * -st_softpipe_surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - *stride * nblocksy); -} - - -static void -st_softpipe_fence_reference(struct pipe_winsys *winsys, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ -} - - -static int -st_softpipe_fence_signalled(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static int -st_softpipe_fence_finish(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static void -st_softpipe_destroy(struct pipe_winsys *winsys) -{ - FREE(winsys); -} - - -static struct pipe_screen * -st_softpipe_screen_create(void) -{ - static struct pipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = CALLOC_STRUCT(pipe_winsys); - if(!winsys) - return NULL; - - winsys->destroy = st_softpipe_destroy; - - winsys->buffer_create = st_softpipe_buffer_create; - winsys->user_buffer_create = st_softpipe_user_buffer_create; - winsys->buffer_map = st_softpipe_buffer_map; - winsys->buffer_unmap = st_softpipe_buffer_unmap; - winsys->buffer_destroy = st_softpipe_buffer_destroy; - - winsys->surface_buffer_create = st_softpipe_surface_buffer_create; - - winsys->fence_reference = st_softpipe_fence_reference; - winsys->fence_signalled = st_softpipe_fence_signalled; - winsys->fence_finish = st_softpipe_fence_finish; - - winsys->flush_frontbuffer = st_softpipe_flush_frontbuffer; - winsys->get_name = st_softpipe_get_name; - - screen = softpipe_create_screen(winsys); - if(!screen) - st_softpipe_destroy(winsys); - - return screen; -} - - -static struct pipe_context * -st_softpipe_context_create(struct pipe_screen *screen) -{ - return softpipe_create(screen); -} - - const struct st_winsys st_softpipe_winsys = { - &st_softpipe_screen_create, - &st_softpipe_context_create, + &softpipe_create_screen_malloc, + &softpipe_create, }; diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-cb-1d.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-cb-1d.sh new file mode 100644 index 0000000000..85fb9ea4e7 --- /dev/null +++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-cb-1d.sh @@ -0,0 +1,13 @@ +FRAG + +DCL IN[0], COLOR, LINEAR +DCL OUT[0], COLOR +DCL CONST[1] +DCL CONST[3] +DCL TEMP[0..1] + +ADD TEMP[0], IN[0], CONST[1] +RCP TEMP[1], CONST[3].xxxx +MUL OUT[0], TEMP[0], TEMP[1] + +END diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-cb-2d.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-cb-2d.sh new file mode 100644 index 0000000000..f70a5146f4 --- /dev/null +++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-cb-2d.sh @@ -0,0 +1,9 @@ +FRAG + +DCL IN[0], COLOR, LINEAR +DCL OUT[0], COLOR +DCL CONST[1][1..2] + +MAD OUT[0], IN[0], CONST[1][2], CONST[1][1] + +END diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh index f2a1521cbf..d58b7886a1 100644 --- a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh +++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh @@ -1,4 +1,4 @@ -FRAG1.1 +FRAG DCL IN[0], COLOR, LINEAR DCL OUT[0], COLOR diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py b/src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py index 8d3bf9d4d7..41dd69d254 100644 --- a/src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py +++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py @@ -26,6 +26,7 @@ # ########################################################################## +import struct from gallium import * @@ -50,11 +51,11 @@ def test(dev, name): # disabled blending/masking blend = Blend() - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.colormask = PIPE_MASK_RGBA + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].colormask = PIPE_MASK_RGBA ctx.set_blend(blend) # depth/stencil/alpha @@ -146,6 +147,42 @@ def test(dev, name): fs = Shader(file('frag-' + name + '.sh', 'rt').read()) ctx.set_fragment_shader(fs) + constbuf0 = dev.buffer_create(64, + (PIPE_BUFFER_USAGE_CONSTANT | + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE), + 4 * 4 * 4) + + cbdata = '' + cbdata += struct.pack('4f', 0.4, 0.0, 0.0, 1.0) + cbdata += struct.pack('4f', 1.0, 1.0, 1.0, 1.0) + cbdata += struct.pack('4f', 2.0, 2.0, 2.0, 2.0) + cbdata += struct.pack('4f', 4.0, 8.0, 16.0, 32.0) + + constbuf0.write(cbdata, 0) + + ctx.set_constant_buffer(PIPE_SHADER_FRAGMENT, + 0, + constbuf0) + + constbuf1 = dev.buffer_create(64, + (PIPE_BUFFER_USAGE_CONSTANT | + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE), + 4 * 4 * 4) + + cbdata = '' + cbdata += struct.pack('4f', 0.1, 0.1, 0.1, 0.1) + cbdata += struct.pack('4f', 0.25, 0.25, 0.25, 0.25) + cbdata += struct.pack('4f', 0.5, 0.5, 0.5, 0.5) + cbdata += struct.pack('4f', 0.75, 0.75, 0.75, 0.75) + + constbuf1.write(cbdata, 0) + + ctx.set_constant_buffer(PIPE_SHADER_FRAGMENT, + 1, + constbuf1) + xy = [ -0.8, -0.8, 0.8, -0.8, @@ -184,6 +221,8 @@ def main(): tests = [ 'abs', 'add', + 'cb-1d', + 'cb-2d', 'dp3', 'dp4', 'dst', diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-cb-1d.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-cb-1d.sh new file mode 100644 index 0000000000..b41fe5dd38 --- /dev/null +++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-cb-1d.sh @@ -0,0 +1,16 @@ +VERT + +DCL IN[0], POSITION +DCL IN[1], COLOR +DCL OUT[0], POSITION +DCL OUT[1], COLOR +DCL CONST[1] +DCL CONST[3] +DCL TEMP[0..1] + +MOV OUT[0], IN[0] +ADD TEMP[0], IN[1], CONST[1] +RCP TEMP[1], CONST[3].xxxx +MUL OUT[1], TEMP[0], TEMP[1] + +END diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-cb-2d.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-cb-2d.sh new file mode 100644 index 0000000000..45f5e6b729 --- /dev/null +++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-cb-2d.sh @@ -0,0 +1,12 @@ +VERT + +DCL IN[0], POSITION +DCL IN[1], COLOR +DCL OUT[0], POSITION +DCL OUT[1], COLOR +DCL CONST[1][1..2] + +MOV OUT[0], IN[0] +MAD OUT[1], IN[1], CONST[1][2], CONST[1][1] + +END diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py index 01bf5a3210..2c44f872e1 100644 --- a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py +++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py @@ -27,6 +27,8 @@ ########################################################################## +import struct + from gallium import * def make_image(surface): @@ -50,11 +52,11 @@ def test(dev, name): # disabled blending/masking blend = Blend() - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.colormask = PIPE_MASK_RGBA + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].colormask = PIPE_MASK_RGBA ctx.set_blend(blend) # depth/stencil/alpha @@ -143,6 +145,42 @@ def test(dev, name): ''') ctx.set_fragment_shader(fs) + constbuf0 = dev.buffer_create(64, + (PIPE_BUFFER_USAGE_CONSTANT | + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE), + 4 * 4 * 4) + + cbdata = '' + cbdata += struct.pack('4f', 0.4, 0.0, 0.0, 1.0) + cbdata += struct.pack('4f', 1.0, 1.0, 1.0, 1.0) + cbdata += struct.pack('4f', 2.0, 2.0, 2.0, 2.0) + cbdata += struct.pack('4f', 4.0, 8.0, 16.0, 32.0) + + constbuf0.write(cbdata, 0) + + ctx.set_constant_buffer(PIPE_SHADER_VERTEX, + 0, + constbuf0) + + constbuf1 = dev.buffer_create(64, + (PIPE_BUFFER_USAGE_CONSTANT | + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE), + 4 * 4 * 4) + + cbdata = '' + cbdata += struct.pack('4f', 0.1, 0.1, 0.1, 0.1) + cbdata += struct.pack('4f', 0.25, 0.25, 0.25, 0.25) + cbdata += struct.pack('4f', 0.5, 0.5, 0.5, 0.5) + cbdata += struct.pack('4f', 0.75, 0.75, 0.75, 0.75) + + constbuf1.write(cbdata, 0) + + ctx.set_constant_buffer(PIPE_SHADER_VERTEX, + 1, + constbuf1) + xy = [ 0.0, 0.8, -0.2, 0.4, @@ -213,6 +251,8 @@ def main(): 'add', 'arl', 'arr', + 'cb-1d', + 'cb-2d', 'dp3', 'dp4', 'dst', diff --git a/src/gallium/state_trackers/python/tests/texture_render.py b/src/gallium/state_trackers/python/tests/texture_render.py index 79287f2cac..0fac1ea5ef 100755 --- a/src/gallium/state_trackers/python/tests/texture_render.py +++ b/src/gallium/state_trackers/python/tests/texture_render.py @@ -115,11 +115,11 @@ class TextureTest(TestCase): # disabled blending/masking blend = Blend() - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.colormask = PIPE_MASK_RGBA + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].colormask = PIPE_MASK_RGBA ctx.set_blend(blend) # no-op depth/stencil/alpha diff --git a/src/gallium/state_trackers/python/tests/texture_sample.py b/src/gallium/state_trackers/python/tests/texture_sample.py index 520961c805..db32b537a1 100755 --- a/src/gallium/state_trackers/python/tests/texture_sample.py +++ b/src/gallium/state_trackers/python/tests/texture_sample.py @@ -140,11 +140,11 @@ class TextureColorSampleTest(TestCase): # disabled blending/masking blend = Blend() - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.colormask = PIPE_MASK_RGBA + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].colormask = PIPE_MASK_RGBA ctx.set_blend(blend) # no-op depth/stencil/alpha @@ -327,11 +327,11 @@ class TextureDepthSampleTest(TestCase): # disabled blending/masking blend = Blend() - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.colormask = PIPE_MASK_RGBA + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.rt[0].colormask = PIPE_MASK_RGBA ctx.set_blend(blend) # depth/stencil/alpha diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile index fc97bf51f8..037d8dc911 100644 --- a/src/gallium/state_trackers/vega/Makefile +++ b/src/gallium/state_trackers/vega/Makefile @@ -1,8 +1,14 @@ -# src/mesa/Makefile +# src/gallium/state_trackers/vega/Makefile TOP = ../../../.. include $(TOP)/configs/current -GALLIUM = $(TOP) + +VG_LIB = OpenVG +VG_LIB_NAME = lib$(VG_LIB).so + +VG_MAJOR = 1 +VG_MINOR = 0 +VG_TINY = 0 ### Lists of source files, included by Makefiles @@ -34,88 +40,54 @@ VG_SOURCES = \ shader.c \ shaders_cache.c +VG_OBJECTS = $(VG_SOURCES:.c=.o) -### All the core C sources - -ALL_SOURCES = \ - $(VG_SOURCES) - - -### Object files -VG_OBJECTS = \ - $(VG_SOURCES:.c=.o) +VG_LIBS = $(GALLIUM_AUXILIARIES) -lm ### Include directories INCLUDE_DIRS = \ -I$(TOP)/include \ - -I$(GALLIUM)/include \ - -I$(GALLIUM)/src/gallium/include \ - -I$(GALLIUM)/src/gallium/auxiliary + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/auxiliary -VG_LIB = OpenVG -VG_LIB_NAME = lib$(VG_LIB).so - -VG_MAJOR = 1 -VG_MINOR = 0 -VG_TINY = 0 - -GALLIUM_LIBS = \ - $(GALLIUM)/src/gallium/auxiliary/libgallium.a - -.SUFFIXES : .cpp .c.o: - $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ + $(CC) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) $< -o $@ -.cpp.o: - $(CXX) -c $(INCLUDE_DIRS) $(CXXFLAGS) $< -o $@ - -.S.o: - $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ - - -default: depend subdirs $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME) +default: depend $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME) # Make the OpenVG library -$(TOP)/$(LIB_DIR)/$(VG_LIB_NAME): $(VG_OBJECTS) $(GALLIUM_LIBS) - $(TOP)/bin/mklib -o $(VG_LIB) \ +$(TOP)/$(LIB_DIR)/$(VG_LIB_NAME): $(VG_OBJECTS) $(VG_LIBS) + $(MKLIB) -o $(VG_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \ -major $(VG_MAJOR) \ -minor $(VG_MINOR) \ -patch $(VG_TINY) \ -install $(TOP)/$(LIB_DIR) \ - $(VG_OBJECTS) $(GALLIUM_LIBS) \ - -Wl,--whole-archive $(LIBS) -Wl,--no-whole-archive $(SYS_LIBS) + $(VG_OBJECTS) $(VG_LIBS) ###################################################################### # Generic stuff -depend: $(ALL_SOURCES) +depend: $(VG_SOURCES) @ echo "running $(MKDEP)" @ rm -f depend # workaround oops on gutsy?!? @ touch depend - @ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \ + @ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(VG_SOURCES) \ > /dev/null 2>/dev/null - -subdirs: - install: default - $(INSTALL) -d $(INSTALL_DIR)/include/VG - $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR) - $(INSTALL) -m 644 $(TOP)/include/VG/*.h $(INSTALL_DIR)/include/VG - @if [ -e $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME) ]; then \ - $(INSTALL) $(TOP)/$(LIB_DIR)/libOpenVG* $(INSTALL_DIR)/$(LIB_DIR); \ - fi + $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/include/VG + $(INSTALL) -m 644 $(TOP)/include/VG/*.h $(DESTDIR)$(INSTALL_DIR)/include/VG + $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR) + $(MINSTALL) $(TOP)/$(LIB_DIR)/libOpenVG* $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR) # Emacs tags tags: etags `find . -name \*.[ch]` $(TOP)/include/VG/*.h clean: - -rm -f *.o - -rm -f */*.o - -rm -f */*/*.o - -rm -f depend depend.bak + rm -f $(VG_OBJECTS) + rm -f depend depend.bak -include depend +sinclude depend diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c index 8f69ee0109..cf4a11bb14 100644 --- a/src/gallium/state_trackers/vega/api_filters.c +++ b/src/gallium/state_trackers/vega/api_filters.c @@ -127,19 +127,19 @@ static void setup_blend() struct vg_context *ctx = vg_current_context(); struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; if (ctx->state.vg.filter_channel_mask & VG_RED) - blend.colormask |= PIPE_MASK_R; + blend.rt[0].colormask |= PIPE_MASK_R; if (ctx->state.vg.filter_channel_mask & VG_GREEN) - blend.colormask |= PIPE_MASK_G; + blend.rt[0].colormask |= PIPE_MASK_G; if (ctx->state.vg.filter_channel_mask & VG_BLUE) - blend.colormask |= PIPE_MASK_B; + blend.rt[0].colormask |= PIPE_MASK_B; if (ctx->state.vg.filter_channel_mask & VG_ALPHA) - blend.colormask |= PIPE_MASK_A; - blend.blend_enable = 1; + blend.rt[0].colormask |= PIPE_MASK_A; + blend.rt[0].blend_enable = 0; cso_set_blend(ctx->cso_context, &blend); } diff --git a/src/gallium/state_trackers/vega/api_masks.c b/src/gallium/state_trackers/vega/api_masks.c index 4f9f3dae17..e6070c7353 100644 --- a/src/gallium/state_trackers/vega/api_masks.c +++ b/src/gallium/state_trackers/vega/api_masks.c @@ -32,7 +32,6 @@ #include "vg_context.h" #include "pipe/p_context.h" #include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" /* for winsys->update_buffer */ #include "util/u_pack_color.h" #include "util/u_draw_quad.h" @@ -116,8 +115,8 @@ clear_with_quad(struct vg_context *st, float x0, float y0, x1, y1); */ - if (st->pipe->winsys && st->pipe->winsys->update_buffer) - st->pipe->winsys->update_buffer( st->pipe->winsys, + if (st->pipe->screen && st->pipe->screen->update_buffer) + st->pipe->screen->update_buffer( st->pipe->screen, st->pipe->priv ); cso_save_blend(st->cso_context); @@ -129,14 +128,11 @@ clear_with_quad(struct vg_context *st, float x0, float y0, { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.colormask |= PIPE_MASK_R; - blend.colormask |= PIPE_MASK_G; - blend.colormask |= PIPE_MASK_B; - blend.colormask |= PIPE_MASK_A; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].colormask = PIPE_MASK_RGBA; cso_set_blend(st->cso_context, &blend); } diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c index 3e260e7073..ba8ecef1d2 100644 --- a/src/gallium/state_trackers/vega/mask.c +++ b/src/gallium/state_trackers/vega/mask.c @@ -354,15 +354,12 @@ static void setup_mask_blend() struct pipe_blend_state blend; memset(&blend, 0, sizeof(struct pipe_blend_state)); - blend.blend_enable = 1; - blend.colormask |= PIPE_MASK_R; - blend.colormask |= PIPE_MASK_G; - blend.colormask |= PIPE_MASK_B; - blend.colormask |= PIPE_MASK_A; - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].blend_enable = 0; + blend.rt[0].colormask = PIPE_MASK_RGBA; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; cso_set_blend(ctx->cso_context, &blend); } diff --git a/src/gallium/state_trackers/vega/polygon.c b/src/gallium/state_trackers/vega/polygon.c index d385ee567f..f5352ee84e 100644 --- a/src/gallium/state_trackers/vega/polygon.c +++ b/src/gallium/state_trackers/vega/polygon.c @@ -248,12 +248,12 @@ VGboolean polygon_is_closed(struct polygon *p) static void set_blend_for_fill(struct pipe_blend_state *blend) { memset(blend, 0, sizeof(struct pipe_blend_state)); - blend->colormask = 0; /*disable colorwrites*/ + blend->rt[0].colormask = 0; /*disable colorwrites*/ - blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend->rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; - blend->alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; } static void draw_polygon(struct vg_context *ctx, diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index 64e3a7c545..47e18dc1e2 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -317,11 +317,11 @@ void renderer_copy_texture(struct renderer *ctx, { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].colormask = PIPE_MASK_RGBA; cso_set_blend(ctx->cso, &blend); } @@ -486,11 +486,11 @@ void renderer_copy_surface(struct renderer *ctx, { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].colormask = PIPE_MASK_RGBA; cso_set_blend(ctx->cso, &blend); } diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c index bd5ae79e55..8e59d53dc7 100644 --- a/src/gallium/state_trackers/vega/shader.c +++ b/src/gallium/state_trackers/vega/shader.c @@ -135,8 +135,8 @@ static VGint blend_bind_samplers(struct vg_context *ctx, textures[2] = stfb->blend_texture; if (!samplers[0] || !textures[0]) { - samplers[1] = samplers[2]; - textures[1] = textures[2]; + samplers[0] = samplers[2]; + textures[0] = textures[2]; } if (!samplers[1] || !textures[1]) { samplers[1] = samplers[0]; diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c index c16ac036e3..64207d97ba 100644 --- a/src/gallium/state_trackers/vega/vg_context.c +++ b/src/gallium/state_trackers/vega/vg_context.c @@ -252,7 +252,7 @@ static void update_clip_state(struct vg_context *ctx) ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0); /* disable color writes */ - blend->colormask = 0; /*disable colorwrites*/ + blend->rt[0].colormask = 0; /*disable colorwrites*/ cso_set_blend(ctx->cso_context, blend); /* enable scissoring */ @@ -286,7 +286,6 @@ static void update_clip_state(struct vg_context *ctx) renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f); } - blend->colormask = 1; /*enable colorwrites*/ cso_restore_blend(ctx->cso_context); cso_restore_fragment_shader(ctx->cso_context); @@ -301,57 +300,56 @@ void vg_validate_state(struct vg_context *ctx) if ((ctx->state.dirty & BLEND_DIRTY)) { struct pipe_blend_state *blend = &ctx->state.g3d.blend; memset(blend, 0, sizeof(struct pipe_blend_state)); - blend->blend_enable = 1; - blend->colormask |= PIPE_MASK_R; - blend->colormask |= PIPE_MASK_G; - blend->colormask |= PIPE_MASK_B; - blend->colormask |= PIPE_MASK_A; + blend->rt[0].blend_enable = 1; + blend->rt[0].colormask = PIPE_MASK_RGBA; switch (ctx->state.vg.blend_mode) { case VG_BLEND_SRC: - blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->rt[0].blend_enable = 0; break; case VG_BLEND_SRC_OVER: - blend->rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; - blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend->rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; - blend->alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; break; case VG_BLEND_DST_OVER: - blend->rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; - blend->alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; - blend->rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; - blend->alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; + blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; + blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; + blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; + blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; break; case VG_BLEND_SRC_IN: - blend->rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; - blend->alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; - blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; + blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; + blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; break; case VG_BLEND_DST_IN: - blend->rgb_src_factor = PIPE_BLENDFACTOR_ZERO; - blend->alpha_src_factor = PIPE_BLENDFACTOR_ZERO; - blend->rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; - blend->alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO; + blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; + blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; break; case VG_BLEND_MULTIPLY: case VG_BLEND_SCREEN: case VG_BLEND_DARKEN: case VG_BLEND_LIGHTEN: - blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->rt[0].blend_enable = 0; break; case VG_BLEND_ADDITIVE: - blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend->rgb_dst_factor = PIPE_BLENDFACTOR_ONE; - blend->alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; break; default: assert(!"not implemented blend mode"); diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h index ff8c1a0421..bc88c8d139 100644 --- a/src/gallium/state_trackers/vega/vg_context.h +++ b/src/gallium/state_trackers/vega/vg_context.h @@ -50,7 +50,7 @@ struct st_renderbuffer { }; struct st_framebuffer { - VGint init_width, init_height; + VGint width, height; struct st_renderbuffer *strb; struct st_renderbuffer *dsrb; diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c index ff80aab03a..617c174eb6 100644 --- a/src/gallium/state_trackers/vega/vg_tracker.c +++ b/src/gallium/state_trackers/vega/vg_tracker.c @@ -193,8 +193,8 @@ struct st_framebuffer * st_create_framebuffer(const void *visual, */ stfb->alpha_mask = 0; - stfb->init_width = width; - stfb->init_height = height; + stfb->width = width; + stfb->height = height; stfb->privateData = privateData; } @@ -282,11 +282,14 @@ void st_resize_framebuffer(struct st_framebuffer *stfb, /* If this is a noop, exit early and don't do the clear, etc below. */ - if (strb->width == width && - strb->height == height && + if (stfb->width == width && + stfb->height == height && state->zsbuf) return; + stfb->width = width; + stfb->height = height; + if (strb->width != width || strb->height != height) st_renderbuffer_alloc_storage(ctx, strb, width, height); diff --git a/src/gallium/state_trackers/wgl/stw_pixelformat.c b/src/gallium/state_trackers/wgl/stw_pixelformat.c index 54cc361412..7d4c2430b0 100644 --- a/src/gallium/state_trackers/wgl/stw_pixelformat.c +++ b/src/gallium/state_trackers/wgl/stw_pixelformat.c @@ -95,8 +95,6 @@ stw_pf_depth_stencil[] = { { PIPE_FORMAT_Z24X8_UNORM, {24, 0} }, { PIPE_FORMAT_X8Z24_UNORM, {24, 0} }, { PIPE_FORMAT_Z16_UNORM, {16, 0} }, - /* pure stencil */ - { PIPE_FORMAT_S8_UNORM, { 0, 8} }, /* combined depth-stencil */ { PIPE_FORMAT_S8Z24_UNORM, {24, 8} }, { PIPE_FORMAT_Z24S8_UNORM, {24, 8} } @@ -220,7 +218,8 @@ stw_pixelformat_init( void ) const struct stw_pf_color_info *color = &stw_pf_color[j]; if(!screen->is_format_supported(screen, color->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) + PIPE_TEXTURE_USAGE_RENDER_TARGET | + PIPE_TEXTURE_USAGE_DISPLAY_TARGET, 0)) continue; for(k = 0; k < Elements(stw_pf_doublebuffer); ++k) { diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c index 1c248a629e..c50873c150 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.c +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -4,10 +4,7 @@ #include "xorg_exa_tgsi.h" #include "cso_cache/cso_context.h" -#include "util/u_draw_quad.h" -#include "util/u_math.h" -#include "pipe/p_inlines.h" /*XXX also in Xrender.h but the including it here breaks compilition */ #define XFixedToDouble(f) (((double) (f)) / 65536.) @@ -220,13 +217,13 @@ bind_blend_state(struct exa_context *exa, int op, blend_for_op(&blend_opt, op, pSrcPicture, pMaskPicture, pDstPicture); memset(&blend, 0, sizeof(struct pipe_blend_state)); - blend.blend_enable = 1; - blend.colormask |= PIPE_MASK_RGBA; + blend.rt[0].blend_enable = 1; + blend.rt[0].colormask = PIPE_MASK_RGBA; - blend.rgb_src_factor = blend_opt.rgb_src; - blend.alpha_src_factor = blend_opt.rgb_src; - blend.rgb_dst_factor = blend_opt.rgb_dst; - blend.alpha_dst_factor = blend_opt.rgb_dst; + blend.rt[0].rgb_src_factor = blend_opt.rgb_src; + blend.rt[0].alpha_src_factor = blend_opt.rgb_src; + blend.rt[0].rgb_dst_factor = blend_opt.rgb_dst; + blend.rt[0].alpha_dst_factor = blend_opt.rgb_dst; cso_set_blend(exa->renderer->cso, &blend); } diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c index 650d2c0d1d..2395d54975 100644 --- a/src/gallium/state_trackers/xorg/xorg_crtc.c +++ b/src/gallium/state_trackers/xorg/xorg_crtc.c @@ -50,7 +50,6 @@ #endif #include "pipe/p_inlines.h" -#include "util/u_format.h" #include "util/u_rect.h" #ifdef HAVE_LIBKMS @@ -243,7 +242,11 @@ crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image) unsigned attr[8]; attr[0] = KMS_BO_TYPE; +#ifdef KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8 + attr[1] = KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8; +#else attr[1] = KMS_BO_TYPE_CURSOR; +#endif attr[2] = KMS_WIDTH; attr[3] = 64; attr[4] = KMS_HEIGHT; diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c index fd82f4fa1d..59588f0ff7 100644 --- a/src/gallium/state_trackers/xorg/xorg_dri2.c +++ b/src/gallium/state_trackers/xorg/xorg_dri2.c @@ -41,12 +41,14 @@ #include "pipe/p_inlines.h" #include "util/u_format.h" -#include "util/u_rect.h" /* Make all the #if cases in the code esier to read */ -/* XXX can it be set to 1? */ #ifndef DRI2INFOREC_VERSION -#define DRI2INFOREC_VERSION 0 +#define DRI2INFOREC_VERSION 1 +#endif + +#if DRI2INFOREC_VERSION == 2 +static Bool set_format_in_do_create_buffer; #endif typedef struct { @@ -147,7 +149,9 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form buffer->driverPrivate = private; buffer->flags = 0; /* not tiled */ #if DRI2INFOREC_VERSION == 2 - ((DRI2Buffer2Ptr)buffer)->format = 0; + /* ABI forwards/backwards compatibility */ + if (set_format_in_do_create_buffer) + ((DRI2Buffer2Ptr)buffer)->format = 0; #elif DRI2INFOREC_VERSION >= 3 buffer->format = 0; #endif @@ -211,7 +215,9 @@ dri2_destroy_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer) xfree(buffer); } -#else /* DRI2INFOREC_VERSION < 2 */ +#endif /* DRI2INFOREC_VERSION >= 2 */ + +#if DRI2INFOREC_VERSION <= 2 static DRI2BufferPtr dri2_create_buffers(DrawablePtr pDraw, unsigned int *attachments, int count) @@ -261,7 +267,7 @@ dri2_destroy_buffers(DrawablePtr pDraw, DRI2BufferPtr buffers, int count) } } -#endif /* DRI2INFOREC_VERSION >= 2 */ +#endif /* DRI2INFOREC_VERSION <= 2 */ static void dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, @@ -369,12 +375,19 @@ xorg_dri2_init(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); DRI2InfoRec dri2info; - #if DRI2INFOREC_VERSION >= 2 - dri2info.version = DRI2INFOREC_VERSION; -#else - dri2info.version = 1; + int major, minor; + + if (xf86LoaderCheckSymbol("DRI2Version")) { + DRI2Version(&major, &minor); + } else { + /* Assume version 1.0 */ + major = 1; + minor = 0; + } #endif + + dri2info.version = DRI2INFOREC_VERSION; dri2info.fd = ms->fd; dri2info.driverName = pScrn->driverName; @@ -383,7 +396,22 @@ xorg_dri2_init(ScreenPtr pScreen) #if DRI2INFOREC_VERSION >= 2 dri2info.CreateBuffer = dri2_create_buffer; dri2info.DestroyBuffer = dri2_destroy_buffer; -#else +#endif + + /* For X servers in the 1.6.x series there where two DRI2 version. + * This allows us to build one binary that works on both servers. + */ +#if DRI2INFOREC_VERSION == 2 + if (minor == 0) { + set_format_in_do_create_buffer = FALSE; + dri2info.CreateBuffers = dri2_create_buffers; + dri2info.DestroyBuffers = dri2_destroy_buffers; + } else + set_format_in_do_create_buffer = FALSE; +#endif + + /* For version 1 set these unconditionaly. */ +#if DRI2INFOREC_VERSION == 1 dri2info.CreateBuffers = dri2_create_buffers; dri2info.DestroyBuffers = dri2_destroy_buffers; #endif diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c index b02fe68f31..f53a879a14 100644 --- a/src/gallium/state_trackers/xorg/xorg_driver.c +++ b/src/gallium/state_trackers/xorg/xorg_driver.c @@ -45,7 +45,6 @@ #include "miscstruct.h" #include "dixstruct.h" #include "xf86xv.h" -#include <X11/extensions/Xv.h> #ifndef XSERVER_LIBPCIACCESS #error "libpciaccess needed" #endif @@ -79,11 +78,13 @@ typedef enum { OPTION_SW_CURSOR, OPTION_2D_ACCEL, + OPTION_DEBUG_FALLBACK, } drv_option_enums; static const OptionInfoRec drv_options[] = { {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_DEBUG_FALLBACK, "DebugFallback", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; @@ -111,6 +112,28 @@ xorg_tracker_set_functions(ScrnInfoPtr scrn) scrn->ValidMode = drv_valid_mode; } +Bool +xorg_tracker_have_modesetting(ScrnInfoPtr pScrn, struct pci_device *device) +{ + char *BusID = xalloc(64); + sprintf(BusID, "pci:%04x:%02x:%02x.%d", + device->domain, device->bus, + device->dev, device->func); + + if (drmCheckModesettingSupported(BusID)) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0, + "Drm modesetting not supported %s\n", BusID); + xfree(BusID); + return FALSE; + } + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0, + "Drm modesetting supported on %s\n", BusID); + + xfree(BusID); + return TRUE; +} + /* * Internal function definitions @@ -206,16 +229,41 @@ drv_init_drm(ScrnInfoPtr pScrn) ms->PciInfo->dev, ms->PciInfo->func ); - ms->fd = drmOpen(NULL, BusID); - if (ms->fd < 0) - return FALSE; + ms->api = drm_api_create(); + ms->fd = drmOpen(ms->api ? ms->api->driver_name : NULL, BusID); + xfree(BusID); + + if (ms->fd >= 0) + return TRUE; + + if (ms->api && ms->api->destroy) + ms->api->destroy(ms->api); + + ms->api = NULL; + + return FALSE; } return TRUE; } static Bool +drv_close_drm(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + + if (ms->api && ms->api->destroy) + ms->api->destroy(ms->api); + ms->api = NULL; + + drmClose(ms->fd); + ms->fd = -1; + + return TRUE; +} + +static Bool drv_init_resource_management(ScrnInfoPtr pScrn) { modesettingPtr ms = modesettingPTR(pScrn); @@ -229,7 +277,6 @@ drv_init_resource_management(ScrnInfoPtr pScrn) if (ms->screen || ms->kms) return TRUE; - ms->api = drm_api_create(); if (ms->api) { ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL); @@ -269,10 +316,6 @@ drv_close_resource_management(ScrnInfoPtr pScrn) } ms->screen = NULL; - if (ms->api && ms->api->destroy) - ms->api->destroy(ms->api); - ms->api = NULL; - #ifdef HAVE_LIBKMS if (ms->kms) kms_destroy(&ms->kms); @@ -629,10 +672,11 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86SetBlackWhitePixels(pScreen); + ms->accelerate_2d = xf86ReturnOptValBool(ms->Options, OPTION_2D_ACCEL, FALSE); + ms->debug_fallback = xf86ReturnOptValBool(ms->Options, OPTION_DEBUG_FALLBACK, TRUE); + if (ms->screen) { - ms->exa = xorg_exa_init(pScrn, xf86ReturnOptValBool(ms->Options, - OPTION_2D_ACCEL, TRUE)); - ms->debug_fallback = debug_get_bool_option("XORG_DEBUG_FALLBACK", TRUE); + ms->exa = xorg_exa_init(pScrn, ms->accelerate_2d); xorg_xv_init(pScreen); #ifdef DRI2 @@ -640,6 +684,17 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #endif } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D Acceleration is %s\n", + ms->screen && ms->accelerate_2d ? "enabled" : "disabled"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Fallback debugging is %s\n", + ms->debug_fallback ? "enabled" : "disabled"); +#ifdef DRI2 + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D Acceleration is %s\n", + ms->screen ? "enabled" : "disabled"); +#else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D Acceleration is disabled\n"); +#endif + miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); xf86SetSilkenMouse(pScreen); @@ -823,8 +878,7 @@ drv_close_screen(int scrnIndex, ScreenPtr pScreen) drv_close_resource_management(pScrn); - drmClose(ms->fd); - ms->fd = -1; + drv_close_drm(pScrn); pScrn->vtSema = FALSE; pScreen->CloseScreen = ms->CloseScreen; @@ -954,7 +1008,11 @@ drv_create_front_buffer_kms(ScrnInfoPtr pScrn) int ret; attr[0] = KMS_BO_TYPE; +#ifdef KMS_BO_TYPE_SCANOUT_X8R8G8B8 + attr[1] = KMS_BO_TYPE_SCANOUT_X8R8G8B8; +#else attr[1] = KMS_BO_TYPE_SCANOUT; +#endif attr[2] = KMS_WIDTH; attr[3] = pScrn->virtualX; attr[4] = KMS_HEIGHT; @@ -1012,12 +1070,22 @@ drv_bind_front_buffer_kms(ScrnInfoPtr pScrn) goto err_destroy; pScreen->ModifyPixmapHeader(rootPixmap, - pScreen->width, - pScreen->height, + pScrn->virtualX, + pScrn->virtualY, pScreen->rootDepth, pScrn->bitsPerPixel, stride, ptr); + + /* This a hack to work around EnableDisableFBAccess setting the pointer + * the real fix would be to replace pScrn->EnableDisableFBAccess hook + * and set the rootPixmap->devPrivate.ptr to something valid before that. + * + * But in its infinit visdome something uses either this some times before + * that, so our hook doesn't get called before the crash happens. + */ + pScrn->pixmapPrivate.ptr = ptr; + return TRUE; err_destroy: diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index d9432babf1..70af0c5fed 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -41,9 +41,7 @@ #include "pipe/p_format.h" #include "pipe/p_context.h" #include "pipe/p_state.h" -#include "pipe/p_inlines.h" -#include "util/u_format.h" #include "util/u_rect.h" #include "util/u_math.h" #include "util/u_debug.h" diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c index bed17caab7..3e5e6bd6a6 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c +++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c @@ -6,11 +6,9 @@ #include "pipe/p_format.h" #include "pipe/p_context.h" #include "pipe/p_state.h" -#include "pipe/p_inlines.h" #include "pipe/p_shader_tokens.h" #include "util/u_memory.h" -#include "util/u_simple_shaders.h" #include "tgsi/tgsi_ureg.h" diff --git a/src/gallium/state_trackers/xorg/xorg_output.c b/src/gallium/state_trackers/xorg/xorg_output.c index 251f331ea7..13c3fb97e3 100644 --- a/src/gallium/state_trackers/xorg/xorg_output.c +++ b/src/gallium/state_trackers/xorg/xorg_output.c @@ -49,8 +49,6 @@ #include <X11/extensions/dpms.h> #endif -#include "X11/Xatom.h" - #include "xorg_tracker.h" static char *output_enum_list[] = { diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c index 8f729b565b..a3c3993ab8 100644 --- a/src/gallium/state_trackers/xorg/xorg_renderer.c +++ b/src/gallium/state_trackers/xorg/xorg_renderer.c @@ -5,7 +5,6 @@ #include "cso_cache/cso_context.h" #include "util/u_draw_quad.h" -#include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_rect.h" @@ -445,11 +444,11 @@ void renderer_copy_prepare(struct xorg_renderer *r, { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].colormask = PIPE_MASK_RGBA; cso_set_blend(r->cso, &blend); } diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h index 4d5d4780dc..a88b1d520d 100644 --- a/src/gallium/state_trackers/xorg/xorg_tracker.h +++ b/src/gallium/state_trackers/xorg/xorg_tracker.h @@ -112,6 +112,7 @@ typedef struct _modesettingRec /* exa */ struct exa_context *exa; Bool noEvict; + Bool accelerate_2d; Bool debug_fallback; /* winsys hocks */ diff --git a/src/gallium/state_trackers/xorg/xorg_winsys.h b/src/gallium/state_trackers/xorg/xorg_winsys.h index 47ee4b9ffd..865733bca2 100644 --- a/src/gallium/state_trackers/xorg/xorg_winsys.h +++ b/src/gallium/state_trackers/xorg/xorg_winsys.h @@ -45,5 +45,6 @@ void xorg_tracker_set_functions(ScrnInfoPtr scrn); const OptionInfoRec * xorg_tracker_available_options(int chipid, int busid); +Bool xorg_tracker_have_modesetting(ScrnInfoPtr pScrn, struct pci_device *device); #endif diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c index 5bf0e94b62..3dcef22c13 100644 --- a/src/gallium/state_trackers/xorg/xorg_xv.c +++ b/src/gallium/state_trackers/xorg/xorg_xv.c @@ -11,9 +11,6 @@ #include "cso_cache/cso_context.h" #include "pipe/p_screen.h" -#include "pipe/p_inlines.h" - -#include "util/u_format.h" /*XXX get these from pipe's texture limits */ #define IMAGE_MAX_WIDTH 2048 @@ -403,14 +400,14 @@ bind_blend_state(struct xorg_xv_port_priv *port) struct pipe_blend_state blend; memset(&blend, 0, sizeof(struct pipe_blend_state)); - blend.blend_enable = 1; - blend.colormask |= PIPE_MASK_RGBA; + blend.rt[0].blend_enable = 0; + blend.rt[0].colormask = PIPE_MASK_RGBA; /* porter&duff src */ - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; cso_set_blend(port->r->cso, &blend); } diff --git a/src/gallium/winsys/drm/Makefile.egl_g3d b/src/gallium/winsys/drm/Makefile.egl index 3ce2725852..b1f2038550 100644 --- a/src/gallium/winsys/drm/Makefile.egl_g3d +++ b/src/gallium/winsys/drm/Makefile.egl @@ -1,4 +1,4 @@ -# src/gallium/winsys/drm/Makefile.egl_g3d +# src/gallium/winsys/drm/Makefile.egl # The driver Makefile should define # @@ -13,10 +13,10 @@ EGL_DRIVER_OBJECTS = $(EGL_DRIVER_SOURCES:.c=.o) common_LIBS = -ldrm -lm -ldl -x11_ST = $(TOP)/src/gallium/state_trackers/egl_g3d/libeglx11.a +x11_ST = $(TOP)/src/gallium/state_trackers/egl/libeglx11.a x11_LIBS = $(common_LIBS) -lX11 -lXext -lXfixes -kms_ST = $(TOP)/src/gallium/state_trackers/egl_g3d/libeglkms.a +kms_ST = $(TOP)/src/gallium/state_trackers/egl/libeglkms.a kms_LIBS = $(common_LIBS) ##### RULES ##### @@ -29,17 +29,16 @@ kms_LIBS = $(common_LIBS) EGL_DISPLAY_DRIVERS = $(foreach dpy, $(EGL_DISPLAYS), egl_$(dpy)_$(EGL_DRIVER_NAME).so) -LIB_GALLIUM_DIR = $(TOP)/$(LIB_DIR)/gallium -EGL_DISPLAY_LIBS = $(foreach drv, $(EGL_DISPLAY_DRIVERS), $(LIB_GALLIUM_DIR)/$(drv)) +EGL_DISPLAY_LIBS = $(foreach drv, $(EGL_DISPLAY_DRIVERS), $(TOP)/$(LIB_DIR)/$(drv)) default: $(EGL_DISPLAY_LIBS) -$(EGL_DISPLAY_LIBS): $(LIB_GALLIUM_DIR)/%.so: %.so - @mkdir -p $(LIB_GALLIUM_DIR) - $(INSTALL) $^ $(LIB_GALLIUM_DIR) +$(EGL_DISPLAY_LIBS): $(TOP)/$(LIB_DIR)/%.so: %.so + $(INSTALL) $< $(TOP)/$(LIB_DIR) define mklib-egl -$(MKLIB) -noprefix -o $@ $(EGL_DRIVER_OBJECTS) \ +$(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + $(MKLIB_OPTIONS) $(EGL_DRIVER_OBJECTS) \ -Wl,--whole-archive $($(1)_ST) -Wl,--no-whole-archive \ $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) $($(1)_LIBS) $(EGL_DRIVER_LIBS) endef @@ -55,10 +54,9 @@ clean: -rm -f $(EGL_DISPLAY_DRIVERS) install: $(EGL_DISPLAY_LIBS) - @$(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) - @echo "Install $(EGL_DISPLAY_DRIVERS)" - @for lib in "$(EGL_DISPLAY_LIBS)"; do \ - $(MINSTALL) -m 755 "$$lib" $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR); \ + $(INSTALL) -d $(DESTDIR)$(EGL_DRIVER_INSTALL_DIR) + for lib in $(EGL_DISPLAY_LIBS); do \ + $(MINSTALL) -m 755 "$$lib" $(DESTDIR)$(EGL_DRIVER_INSTALL_DIR); \ done depend: diff --git a/src/gallium/winsys/drm/Makefile.template b/src/gallium/winsys/drm/Makefile.template index 9635c3c50e..960353a73d 100644 --- a/src/gallium/winsys/drm/Makefile.template +++ b/src/gallium/winsys/drm/Makefile.template @@ -82,18 +82,11 @@ SHARED_INCLUDES = \ default: depend symlinks $(TOP)/$(LIB_DIR)/gallium/$(LIBNAME) $(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template - $(MKLIB) -noprefix -o $@ \ + $(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ $(OBJECTS) $(PIPE_DRIVERS) \ -Wl,--start-group $(MESA_MODULES) -Wl,--end-group \ $(WINOBJ) $(DRI_LIB_DEPS) $(DRIVER_EXTRAS) -$(LIBNAME_EGL): $(WINSYS_OBJECTS) $(LIBS) - $(MKLIB) -o $(LIBNAME_EGL) \ - -linker "$(CC)" \ - -noprefix \ - $(OBJECTS) $(MKLIB_OPTIONS) $(WINSYS_OBJECTS) $(PIPE_DRIVERS) $(WINOBJ) $(DRI_LIB_DEPS) \ - --whole-archive $(LIBS) $(GALLIUM_AUXILIARIES) --no-whole-archive $(DRIVER_EXTRAS) - $(TOP)/$(LIB_DIR)/gallium: mkdir -p $@ diff --git a/src/gallium/winsys/drm/i965/egl/Makefile b/src/gallium/winsys/drm/i965/egl/Makefile index a1b32eb2a7..1c13258200 100644 --- a/src/gallium/winsys/drm/i965/egl/Makefile +++ b/src/gallium/winsys/drm/i965/egl/Makefile @@ -1,29 +1,14 @@ TOP = ../../../../../.. -GALLIUMDIR = ../../../.. include $(TOP)/configs/current -LIBNAME = EGL_i965.so +EGL_DRIVER_NAME = i965 +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_intel -PIPE_DRIVERS = \ - $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ - $(GALLIUMDIR)/winsys/drm/i965/gem/libi965drm.a \ +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/i965/libi965.a -DRIVER_SOURCES = - -C_SOURCES = \ - $(COMMON_GALLIUM_SOURCES) \ - $(DRIVER_SOURCES) - -DRIVER_EXTRAS = -ldrm_intel - -ASM_SOURCES = - -DRIVER_DEFINES = -I../gem $(shell pkg-config libdrm --atleast-version=2.3.1 \ - && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP") - -include ../../Makefile.template - -symlinks: +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/i965/egl_g3d/dummy.c b/src/gallium/winsys/drm/i965/egl/dummy.c index 4a1bc28b0b..4a1bc28b0b 100644 --- a/src/gallium/winsys/drm/i965/egl_g3d/dummy.c +++ b/src/gallium/winsys/drm/i965/egl/dummy.c diff --git a/src/gallium/winsys/drm/i965/egl_g3d/Makefile b/src/gallium/winsys/drm/i965/egl_g3d/Makefile deleted file mode 100644 index dd2efe2485..0000000000 --- a/src/gallium/winsys/drm/i965/egl_g3d/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -TOP = ../../../../../.. -include $(TOP)/configs/current - -EGL_DRIVER_NAME = i965 -EGL_DRIVER_SOURCES = dummy.c -EGL_DRIVER_LIBS = -ldrm_intel - -EGL_DRIVER_PIPES = \ - $(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \ - $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ - $(TOP)/src/gallium/drivers/trace/libtrace.a \ - $(TOP)/src/gallium/drivers/i965/libi965.a - -include ../../Makefile.egl_g3d diff --git a/src/gallium/winsys/drm/i965/xorg/Makefile b/src/gallium/winsys/drm/i965/xorg/Makefile index 65d521fc1c..c25726b0bb 100644 --- a/src/gallium/winsys/drm/i965/xorg/Makefile +++ b/src/gallium/winsys/drm/i965/xorg/Makefile @@ -36,7 +36,7 @@ all default: $(TARGET) $(TARGET_STAGING) $(TARGET): $(OBJECTS) Makefile $(GALLIUMDIR)/state_trackers/xorg/libxorgtracker.a $(LIBS) $(TOP)/bin/mklib -noprefix -o $@ \ - $(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_radeon + $(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_intel $(TOP)/$(LIB_DIR)/gallium: mkdir -p $@ diff --git a/src/gallium/winsys/drm/intel/egl/Makefile b/src/gallium/winsys/drm/intel/egl/Makefile index 1397e9f729..60d675ca73 100644 --- a/src/gallium/winsys/drm/intel/egl/Makefile +++ b/src/gallium/winsys/drm/intel/egl/Makefile @@ -1,29 +1,14 @@ TOP = ../../../../../.. -GALLIUMDIR = ../../../.. include $(TOP)/configs/current -LIBNAME = EGL_i915.so +EGL_DRIVER_NAME = i915 +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_intel -PIPE_DRIVERS = \ - $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ - $(GALLIUMDIR)/winsys/drm/intel/gem/libinteldrm.a \ +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/i915/libi915.a -DRIVER_SOURCES = - -C_SOURCES = \ - $(COMMON_GALLIUM_SOURCES) \ - $(DRIVER_SOURCES) - -DRIVER_EXTRAS = -ldrm_intel - -ASM_SOURCES = - -DRIVER_DEFINES = -I../gem $(shell pkg-config libdrm --atleast-version=2.3.1 \ - && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP") - -include ../../Makefile.template - -symlinks: +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/intel/egl_g3d/dummy.c b/src/gallium/winsys/drm/intel/egl/dummy.c index 4a1bc28b0b..4a1bc28b0b 100644 --- a/src/gallium/winsys/drm/intel/egl_g3d/dummy.c +++ b/src/gallium/winsys/drm/intel/egl/dummy.c diff --git a/src/gallium/winsys/drm/intel/egl_g3d/Makefile b/src/gallium/winsys/drm/intel/egl_g3d/Makefile deleted file mode 100644 index cdbb680773..0000000000 --- a/src/gallium/winsys/drm/intel/egl_g3d/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -TOP = ../../../../../.. -include $(TOP)/configs/current - -EGL_DRIVER_NAME = i915 -EGL_DRIVER_SOURCES = dummy.c -EGL_DRIVER_LIBS = -ldrm_intel - -EGL_DRIVER_PIPES = \ - $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \ - $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ - $(TOP)/src/gallium/drivers/trace/libtrace.a \ - $(TOP)/src/gallium/drivers/i915/libi915.a - -include ../../Makefile.egl_g3d diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_api.c b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c index 450ae09b34..8c8176e44a 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_drm_api.c +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c @@ -196,6 +196,7 @@ destroy(struct drm_api *api) struct drm_api intel_drm_api = { .name = "i915", + .driver_name = "i915", .create_context = intel_drm_create_context, .create_screen = intel_drm_create_screen, .texture_from_shared_handle = intel_drm_texture_from_shared_handle, diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c index 4b2c6a1025..75cd1e2902 100644 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c @@ -54,6 +54,16 @@ static struct dri1_api nouveau_dri1_api = { nouveau_dri1_front_surface, }; +static void +nouveau_drm_destroy_winsys(struct pipe_winsys *s) +{ + struct nouveau_winsys *nv_winsys = nouveau_winsys(s); + struct nouveau_screen *nv_screen= nouveau_screen(nv_winsys->pscreen); + nouveau_device_close(&nv_screen->device); + FREE(nv_winsys->pctx); + FREE(nv_winsys); +} + static struct pipe_screen * nouveau_drm_create_screen(struct drm_api *api, int fd, struct drm_create_screen_arg *arg) @@ -105,6 +115,7 @@ nouveau_drm_create_screen(struct drm_api *api, int fd, return NULL; } ws = &nvws->base; + ws->destroy = nouveau_drm_destroy_winsys; nvws->pscreen = init(ws, dev); if (!nvws->pscreen) { @@ -255,6 +266,7 @@ nouveau_drm_handle_from_pt(struct drm_api *api, struct pipe_screen *pscreen, struct drm_api drm_api_hooks = { .name = "nouveau", + .driver_name = "nouveau", .create_screen = nouveau_drm_create_screen, .create_context = nouveau_drm_create_context, .texture_from_shared_handle = nouveau_drm_pt_from_name, diff --git a/src/gallium/winsys/drm/nouveau/egl_g3d/Makefile b/src/gallium/winsys/drm/nouveau/egl/Makefile index 865a5d56a9..8e812acc86 100644 --- a/src/gallium/winsys/drm/nouveau/egl_g3d/Makefile +++ b/src/gallium/winsys/drm/nouveau/egl/Makefile @@ -16,4 +16,4 @@ EGL_DRIVER_PIPES = \ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a -include ../../Makefile.egl_g3d +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c b/src/gallium/winsys/drm/nouveau/egl/dummy.c index 4a1bc28b0b..4a1bc28b0b 100644 --- a/src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c +++ b/src/gallium/winsys/drm/nouveau/egl/dummy.c diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c index 385fa857b5..f484503e0e 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c @@ -51,6 +51,26 @@ static const char *radeon_get_name(struct pipe_winsys *ws) return "Radeon/GEM+KMS"; } +static uint32_t radeon_domain_from_usage(unsigned usage) +{ + uint32_t domain = 0; + + if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) { + domain |= RADEON_GEM_DOMAIN_VRAM; + } + if (usage & PIPE_BUFFER_USAGE_PIXEL) { + domain |= RADEON_GEM_DOMAIN_VRAM; + } + if (usage & PIPE_BUFFER_USAGE_VERTEX) { + domain |= RADEON_GEM_DOMAIN_GTT; + } + if (usage & PIPE_BUFFER_USAGE_INDEX) { + domain |= RADEON_GEM_DOMAIN_GTT; + } + + return domain; +} + static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws, unsigned alignment, unsigned usage, @@ -58,6 +78,7 @@ static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws, { struct radeon_winsys *radeon_ws = (struct radeon_winsys *)ws; struct radeon_pipe_buffer *radeon_buffer; + struct pb_desc desc; uint32_t domain; radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer); @@ -70,18 +91,16 @@ static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws, radeon_buffer->base.usage = usage; radeon_buffer->base.size = size; - domain = 0; - - if (usage & PIPE_BUFFER_USAGE_PIXEL) { - domain |= RADEON_GEM_DOMAIN_VRAM; - } - if (usage & PIPE_BUFFER_USAGE_VERTEX) { - domain |= RADEON_GEM_DOMAIN_GTT; - } - if (usage & PIPE_BUFFER_USAGE_INDEX) { - domain |= RADEON_GEM_DOMAIN_GTT; + if (usage & PIPE_BUFFER_USAGE_CONSTANT && is_r3xx(radeon_ws->pci_id)) { + /* Don't bother allocating a BO, as it'll never get to the card. */ + desc.alignment = alignment; + desc.usage = usage; + radeon_buffer->pb = pb_malloc_buffer_create(size, &desc); + return &radeon_buffer->base; } + domain = radeon_domain_from_usage(usage); + radeon_buffer->bo = radeon_bo_open(radeon_ws->priv->bom, 0, size, alignment, domain, 0); if (radeon_buffer->bo == NULL) { @@ -133,8 +152,16 @@ static void radeon_buffer_del(struct pipe_buffer *buffer) struct radeon_pipe_buffer *radeon_buffer = (struct radeon_pipe_buffer*)buffer; - radeon_bo_unref(radeon_buffer->bo); - free(radeon_buffer); + if (radeon_buffer->pb) { + pipe_reference_init(&radeon_buffer->pb->base.reference, 0); + pb_destroy(radeon_buffer->pb); + } + + if (radeon_buffer->bo) { + radeon_bo_unref(radeon_buffer->bo); + } + + FREE(radeon_buffer); } static void *radeon_buffer_map(struct pipe_winsys *ws, @@ -146,6 +173,10 @@ static void *radeon_buffer_map(struct pipe_winsys *ws, (struct radeon_pipe_buffer*)buffer; int write = 0; + if (radeon_buffer->pb) { + return pb_map(radeon_buffer->pb, flags); + } + if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { uint32_t domain; @@ -174,7 +205,31 @@ static void radeon_buffer_unmap(struct pipe_winsys *ws, struct radeon_pipe_buffer *radeon_buffer = (struct radeon_pipe_buffer*)buffer; - radeon_bo_unmap(radeon_buffer->bo); + if (radeon_buffer->pb) { + pb_unmap(radeon_buffer->pb); + } else { + radeon_bo_unmap(radeon_buffer->bo); + } +} + +static void radeon_buffer_set_tiling(struct radeon_winsys *ws, + struct pipe_buffer *buffer, + uint32_t pitch, + boolean microtiled, + boolean macrotiled) +{ + struct radeon_pipe_buffer *radeon_buffer = + (struct radeon_pipe_buffer*)buffer; + uint32_t flags = 0; + + if (microtiled) { + flags |= RADEON_BO_FLAGS_MICRO_TILE; + } + if (macrotiled) { + flags |= RADEON_BO_FLAGS_MACRO_TILE; + } + + radeon_bo_set_tiling(radeon_buffer->bo, flags, pitch); } static void radeon_fence_reference(struct pipe_winsys *ws, @@ -279,5 +334,7 @@ struct radeon_winsys* radeon_pipe_winsys(int fd) radeon_ws->base.get_name = radeon_get_name; + radeon_ws->buffer_set_tiling = radeon_buffer_set_tiling; + return radeon_ws; } diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h index d7f17564a9..de71cb2f42 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h @@ -36,7 +36,7 @@ #include "pipe/p_defines.h" #include "pipe/p_inlines.h" -//#include "state_tracker/st_public.h" +#include "pipebuffer/pb_buffer.h" #include "util/u_memory.h" @@ -49,7 +49,10 @@ struct radeon_pipe_buffer { struct pipe_buffer base; + /* Pointer to GPU-backed BO. */ struct radeon_bo *bo; + /* Pointer to fallback PB buffer. */ + struct pb_buffer *pb; boolean flinked; uint32_t flink; }; diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.c b/src/gallium/winsys/drm/radeon/core/radeon_drm.c index 851c223697..bff6fdc1ad 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.c @@ -40,12 +40,16 @@ static void do_ioctls(int fd, struct radeon_winsys* winsys) struct drm_radeon_info info = {0}; int target = 0; int retval; + drmVersionPtr version; info.value = (unsigned long)⌖ /* We do things in a specific order here. * - * First, the PCI ID. This is essential and should return usable numbers + * DRM version first. We need to be sure we're running on a KMS chipset. + * This is also for some features. + * + * Then, the PCI ID. This is essential and should return usable numbers * for all Radeons. If this fails, we probably got handed an FD for some * non-Radeon card. * @@ -55,8 +59,18 @@ static void do_ioctls(int fd, struct radeon_winsys* winsys) * * The GEM info is actually bogus on the kernel side, as well as our side * (see radeon_gem_info_ioctl in radeon_gem.c) but that's alright because - * we don't actually use the info for anything yet. - * XXX update the above when we can safely use vram_size instead of vram_visible */ + * we don't actually use the info for anything yet. */ + + version = drmGetVersion(fd); + if (version->version_major != 2) { + fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is " + "only compatible with 2.x.x\n", __FUNCTION__, + version->version_major, version->version_minor, + version->version_patchlevel); + drmFreeVersion(version); + exit(1); + } + info.request = RADEON_INFO_DEVICE_ID; retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); if (retval) { @@ -92,16 +106,18 @@ static void do_ioctls(int fd, struct radeon_winsys* winsys) exit(1); } winsys->gart_size = gem_info.gart_size; - /* XXX */ - winsys->vram_size = gem_info.vram_visible; -} - -/* Guess at whether this chipset should use r300g. - * - * I believe that this check is valid, but I haven't been exhaustive. */ -static boolean is_r3xx(int pciid) -{ - return (pciid > 0x3150) && (pciid < 0x796f); + winsys->vram_size = gem_info.vram_size; + + debug_printf("radeon: Successfully grabbed chipset info from kernel!\n" + "radeon: DRM version: %d.%d.%d ID: 0x%04x GB: %d Z: %d\n" + "radeon: GART size: %d MB VRAM size: %d MB\n", + version->version_major, version->version_minor, + version->version_patchlevel, winsys->pci_id, + winsys->gb_pipes, winsys->z_pipes, + winsys->gart_size / 1024 / 1024, + winsys->vram_size / 1024 / 1024); + + drmFreeVersion(version); } /* Create a pipe_screen. */ @@ -136,12 +152,13 @@ struct pipe_context* radeon_create_context(struct drm_api* api, } boolean radeon_buffer_from_texture(struct drm_api* api, + struct pipe_screen* screen, struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride) { /* XXX fix this */ - return r300_get_texture_buffer(texture, buffer, stride); + return r300_get_texture_buffer(screen, texture, buffer, stride); } /* Create a buffer from a handle. */ @@ -208,7 +225,7 @@ static boolean radeon_shared_handle_from_texture(struct drm_api *api, struct radeon_pipe_buffer* radeon_buffer; struct pipe_buffer *buffer = NULL; - if (!radeon_buffer_from_texture(api, texture, &buffer, stride)) { + if (!radeon_buffer_from_texture(api, screen, texture, &buffer, stride)) { return FALSE; } @@ -240,7 +257,7 @@ static boolean radeon_local_handle_from_texture(struct drm_api *api, unsigned *handle) { struct pipe_buffer *buffer = NULL; - if (!radeon_buffer_from_texture(api, texture, &buffer, stride)) { + if (!radeon_buffer_from_texture(api, screen, texture, &buffer, stride)) { return FALSE; } @@ -253,6 +270,7 @@ static boolean radeon_local_handle_from_texture(struct drm_api *api, struct drm_api drm_api_hooks = { .name = "radeon", + .driver_name = "radeon", .create_screen = radeon_create_screen, .create_context = radeon_create_context, .texture_from_shared_handle = radeon_texture_from_shared_handle, diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.h b/src/gallium/winsys/drm/radeon/core/radeon_drm.h index bf0e78138d..077388ee02 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.h @@ -56,6 +56,7 @@ struct pipe_context* radeon_create_context(struct drm_api* api, struct pipe_screen* screen); boolean radeon_buffer_from_texture(struct drm_api* api, + struct pipe_screen* screen, struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride); @@ -76,4 +77,13 @@ boolean radeon_global_handle_from_buffer(struct drm_api* api, unsigned* handle); void radeon_destroy_drm_api(struct drm_api* api); + +/* Guess at whether this chipset should use r300g. + * + * I believe that this check is valid, but I haven't been exhaustive. */ +static INLINE boolean is_r3xx(int pciid) +{ + return (pciid > 0x3150) && (pciid < 0x796f); +} + #endif diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.c b/src/gallium/winsys/drm/radeon/core/radeon_r300.c index 0875ee41cb..d759beaba1 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.c @@ -81,9 +81,13 @@ static void radeon_write_cs_reloc(struct radeon_winsys* winsys, uint32_t flags) { int retval = 0; + struct radeon_pipe_buffer* radeon_buffer = + (struct radeon_pipe_buffer*)pbuffer; - retval = radeon_cs_write_reloc(winsys->priv->cs, - ((struct radeon_pipe_buffer*)pbuffer)->bo, rd, wd, flags); + assert(!radeon_buffer->pb); + + retval = radeon_cs_write_reloc(winsys->priv->cs, radeon_buffer->bo, + rd, wd, flags); if (retval) { debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n", @@ -108,6 +112,11 @@ static void radeon_flush_cs(struct radeon_winsys* winsys) { int retval; + /* Don't flush a zero-sized CS. */ + if (!winsys->priv->cs->cdw) { + return; + } + /* Emit the CS. */ retval = radeon_cs_emit(winsys->priv->cs); if (retval) { diff --git a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h index 9edc9e038c..864082b99b 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h @@ -100,6 +100,12 @@ struct radeon_winsys { void (*flush_cb)(void *), void *data); void (*reset_bos)(struct radeon_winsys *winsys); + + void (*buffer_set_tiling)(struct radeon_winsys* winsys, + struct pipe_buffer* buffer, + uint32_t pitch, + boolean microtiled, + boolean macrotiled); }; #endif diff --git a/src/gallium/winsys/drm/radeon/egl/Makefile b/src/gallium/winsys/drm/radeon/egl/Makefile index 6a1448d1b9..cd4f9b20f0 100644 --- a/src/gallium/winsys/drm/radeon/egl/Makefile +++ b/src/gallium/winsys/drm/radeon/egl/Makefile @@ -1,26 +1,14 @@ TOP = ../../../../../.. -GALLIUMDIR = ../../../.. include $(TOP)/configs/current -LIBNAME = EGL_r300.so +EGL_DRIVER_NAME = radeon +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_radeon -PIPE_DRIVERS = \ - $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ - $(GALLIUMDIR)/winsys/drm/radeon/core/libradeonwinsys.a \ +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/radeon/core/libradeonwinsys.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/r300/libr300.a -DRIVER_SOURCES = - -C_SOURCES = \ - $(COMMON_GALLIUM_SOURCES) \ - $(DRIVER_SOURCES) - -DRIVER_EXTRAS = -ldrm_radeon - -ASM_SOURCES = - -include ../../Makefile.template - -symlinks: +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/radeon/egl_g3d/dummy.c b/src/gallium/winsys/drm/radeon/egl/dummy.c index 4a1bc28b0b..4a1bc28b0b 100644 --- a/src/gallium/winsys/drm/radeon/egl_g3d/dummy.c +++ b/src/gallium/winsys/drm/radeon/egl/dummy.c diff --git a/src/gallium/winsys/drm/radeon/egl_g3d/Makefile b/src/gallium/winsys/drm/radeon/egl_g3d/Makefile deleted file mode 100644 index 9027a5ff46..0000000000 --- a/src/gallium/winsys/drm/radeon/egl_g3d/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -TOP = ../../../../../.. -include $(TOP)/configs/current - -EGL_DRIVER_NAME = r300 -EGL_DRIVER_SOURCES = dummy.c -EGL_DRIVER_LIBS = -ldrm_radeon - -EGL_DRIVER_PIPES = \ - $(TOP)/src/gallium/winsys/drm/radeon/core/libradeonwinsys.a \ - $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ - $(TOP)/src/gallium/drivers/trace/libtrace.a \ - $(TOP)/src/gallium/drivers/r300/libr300.a - -include ../../Makefile.egl_g3d diff --git a/src/gallium/winsys/drm/swrast/Makefile b/src/gallium/winsys/drm/swrast/Makefile new file mode 100644 index 0000000000..363b89584f --- /dev/null +++ b/src/gallium/winsys/drm/swrast/Makefile @@ -0,0 +1,12 @@ +# src/gallium/winsys/drm/swrast/Makefile +TOP = ../../../../.. +include $(TOP)/configs/current + +SUBDIRS = core $(GALLIUM_STATE_TRACKERS_DIRS) + +default install clean: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE) $@) || exit 1; \ + fi \ + done diff --git a/src/gallium/winsys/drm/swrast/core/Makefile b/src/gallium/winsys/drm/swrast/core/Makefile new file mode 100644 index 0000000000..93931ae22b --- /dev/null +++ b/src/gallium/winsys/drm/swrast/core/Makefile @@ -0,0 +1,10 @@ +# src/gallium/winsys/drm/swrast/core/Makefile + +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBNAME = swrastdrm + +C_SOURCES = swrast_drm_api.c + +include ../../../../Makefile.template diff --git a/src/gallium/winsys/drm/swrast/core/swrast_drm_api.c b/src/gallium/winsys/drm/swrast/core/swrast_drm_api.c new file mode 100644 index 0000000000..8c9f80e2c1 --- /dev/null +++ b/src/gallium/winsys/drm/swrast/core/swrast_drm_api.c @@ -0,0 +1,13 @@ +#include "state_tracker/drm_api.h" + +static struct drm_api swrast_drm_api = +{ + .name = "swrast", +}; + +struct drm_api * +drm_api_create() +{ + (void) swrast_drm_api; + return NULL; +} diff --git a/src/gallium/winsys/drm/swrast/egl/Makefile b/src/gallium/winsys/drm/swrast/egl/Makefile new file mode 100644 index 0000000000..26fe2d2805 --- /dev/null +++ b/src/gallium/winsys/drm/swrast/egl/Makefile @@ -0,0 +1,12 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +EGL_DRIVER_NAME = swrast +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = + +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/swrast/core/libswrastdrm.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a + +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/vmware/egl_g3d/dummy.c b/src/gallium/winsys/drm/swrast/egl/dummy.c index 4a1bc28b0b..4a1bc28b0b 100644 --- a/src/gallium/winsys/drm/vmware/egl_g3d/dummy.c +++ b/src/gallium/winsys/drm/swrast/egl/dummy.c diff --git a/src/gallium/winsys/drm/vmware/core/vmw_context.c b/src/gallium/winsys/drm/vmware/core/vmw_context.c index b6997588de..b5fd4f5a6a 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_context.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_context.c @@ -41,9 +41,18 @@ #define VMW_COMMAND_SIZE (64*1024) #define VMW_SURFACE_RELOCS (1024) +#define VMW_REGION_RELOCS (512) #define VMW_MUST_FLUSH_STACK 8 +struct vmw_region_relocation +{ + struct SVGAGuestPtr *where; + struct pb_buffer *buffer; + /* TODO: put offset info inside where */ + uint32 offset; +}; + struct vmw_svga_winsys_context { struct svga_winsys_context base; @@ -69,10 +78,31 @@ struct vmw_svga_winsys_context uint32_t staged; uint32_t reserved; } surface; + + struct { + struct vmw_region_relocation relocs[VMW_REGION_RELOCS]; + uint32_t size; + uint32_t used; + uint32_t staged; + uint32_t reserved; + } region; struct pb_validate *validate; uint32_t last_fence; + + /** + * The amount of GMR that is referred by the commands currently batched + * in the context. + */ + uint32_t seen_regions; + + /** + * Whether this context should fail to reserve more commands, not because it + * ran out of command space, but because a substantial ammount of GMR was + * referred. + */ + boolean preemptive_flush; }; @@ -96,6 +126,19 @@ vmw_swc_flush(struct svga_winsys_context *swc, ret = pb_validate_validate(vswc->validate); assert(ret == PIPE_OK); if(ret == PIPE_OK) { + + /* Apply relocations */ + for(i = 0; i < vswc->region.used; ++i) { + struct vmw_region_relocation *reloc = &vswc->region.relocs[i]; + struct SVGAGuestPtr ptr; + + if(!vmw_gmr_bufmgr_region_ptr(reloc->buffer, &ptr)) + assert(0); + + ptr.offset += reloc->offset; + + *reloc->where = ptr; + } if (vswc->command.used) vmw_ioctl_command(vswc->vws, @@ -121,9 +164,18 @@ vmw_swc_flush(struct svga_winsys_context *swc, vswc->surface.used = 0; vswc->surface.reserved = 0; + for(i = 0; i < vswc->region.used + vswc->region.staged; ++i) { + pb_reference(&vswc->region.relocs[i].buffer, NULL); + } + + vswc->region.used = 0; + vswc->region.reserved = 0; + #ifdef DEBUG vswc->must_flush = FALSE; #endif + vswc->preemptive_flush = FALSE; + vswc->seen_regions = 0; if(pfence) *pfence = fence; @@ -151,8 +203,10 @@ vmw_swc_reserve(struct svga_winsys_context *swc, if(nr_bytes > vswc->command.size) return NULL; - if(vswc->command.used + nr_bytes > vswc->command.size || - vswc->surface.used + nr_relocs > vswc->surface.size) { + if(vswc->preemptive_flush || + vswc->command.used + nr_bytes > vswc->command.size || + vswc->surface.used + nr_relocs > vswc->surface.size || + vswc->region.used + nr_relocs > vswc->region.size) { #ifdef DEBUG vswc->must_flush = TRUE; debug_backtrace_capture(vswc->must_flush_stack, 1, @@ -163,11 +217,14 @@ vmw_swc_reserve(struct svga_winsys_context *swc, assert(vswc->command.used + nr_bytes <= vswc->command.size); assert(vswc->surface.used + nr_relocs <= vswc->surface.size); - + assert(vswc->region.used + nr_relocs <= vswc->region.size); + vswc->command.reserved = nr_bytes; vswc->surface.reserved = nr_relocs; vswc->surface.staged = 0; - + vswc->region.reserved = nr_relocs; + vswc->region.staged = 0; + return vswc->command.buffer + vswc->command.used; } @@ -206,20 +263,41 @@ vmw_swc_region_relocation(struct svga_winsys_context *swc, unsigned flags) { struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); - struct SVGAGuestPtr ptr; - struct pb_buffer *buf = vmw_pb_buffer(buffer); + struct vmw_region_relocation *reloc; enum pipe_error ret; + + assert(vswc->region.staged < vswc->region.reserved); - if(!vmw_gmr_bufmgr_region_ptr(buf, &ptr)) - assert(0); - - ptr.offset += offset; + reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged]; + reloc->where = where; + pb_reference(&reloc->buffer, vmw_pb_buffer(buffer)); + reloc->offset = offset; - *where = ptr; + ++vswc->region.staged; - ret = pb_validate_add_buffer(vswc->validate, buf, flags); + ret = pb_validate_add_buffer(vswc->validate, reloc->buffer, flags); /* TODO: Update pipebuffer to reserve buffers and not fail here */ assert(ret == PIPE_OK); + + /* + * Flush preemptively the FIFO commands to keep the GMR working set within + * the GMR pool size. + * + * This is necessary for applications like SPECviewperf that generate huge + * amounts of immediate vertex data, so that we don't pile up too much of + * that vertex data neither in the guest nor in the host. + * + * Note that in the current implementation if a region is referred twice in + * a command stream, it will be accounted twice. We could detect repeated + * regions and count only once, but there is no incentive to do that, since + * regions are typically short-lived; always referred in a single command; + * and at the worst we just flush the commands a bit sooner, which for the + * SVGA virtual device it's not a performance issue since flushing commands + * to the FIFO won't cause flushing in the host. + */ + vswc->seen_regions += reloc->buffer->base.size; + if(vswc->seen_regions >= VMW_GMR_POOL_SIZE/2) + vswc->preemptive_flush = TRUE; } @@ -238,6 +316,12 @@ vmw_swc_commit(struct svga_winsys_context *swc) vswc->surface.used += vswc->surface.staged; vswc->surface.staged = 0; vswc->surface.reserved = 0; + + assert(vswc->region.staged <= vswc->region.reserved); + assert(vswc->region.used + vswc->region.staged <= vswc->region.size); + vswc->region.used += vswc->region.staged; + vswc->region.staged = 0; + vswc->region.reserved = 0; } @@ -246,6 +330,11 @@ vmw_swc_destroy(struct svga_winsys_context *swc) { struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); unsigned i; + + for(i = 0; i < vswc->region.used; ++i) { + pb_reference(&vswc->region.relocs[i].buffer, NULL); + } + for(i = 0; i < vswc->surface.used; ++i) { p_atomic_dec(&vswc->surface.handles[i]->validated); vmw_svga_winsys_surface_reference(&vswc->surface.handles[i], NULL); @@ -279,6 +368,7 @@ vmw_svga_winsys_context_create(struct svga_winsys_screen *sws) vswc->command.size = VMW_COMMAND_SIZE; vswc->surface.size = VMW_SURFACE_RELOCS; + vswc->region.size = VMW_REGION_RELOCS; vswc->validate = pb_validate_create(); if(!vswc->validate) { diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen.h b/src/gallium/winsys/drm/vmware/core/vmw_screen.h index a875107370..f1d69865e7 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_screen.h +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen.h @@ -40,6 +40,10 @@ #include "svga_winsys.h" + +#define VMW_GMR_POOL_SIZE (16*1024*1024) + + struct pb_manager; struct vmw_region; diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c index 4f5ccea467..d9abde3079 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c @@ -85,6 +85,23 @@ vmw_drm_create_screen(struct drm_api *drm_api, struct pipe_screen *screen; struct dri1_create_screen_arg *dri1; + if (!arg || arg->mode == DRM_CREATE_NORMAL) { + struct dri1_api_version drm_ver; + drmVersionPtr ver; + + ver = drmGetVersion(fd); + if (ver == NULL) + return NULL; + + drm_ver.major = ver->version_major; + drm_ver.minor = ver->version_minor; + + drmFreeVersion(ver); + if (!vmw_dri1_check_version(&drm_ver, &drm_required, + &drm_compat, "vmwgfx drm driver")) + return NULL; + } + if (arg != NULL) { switch (arg->mode) { case DRM_CREATE_NORMAL: @@ -220,22 +237,19 @@ vmw_dri1_present_locked(struct pipe_context *locked_pipe, vmw_svga_winsys_surface_reference(&vsrf, NULL); } -/** - * FIXME: We'd probably want to cache these buffers in the - * screen, based on handle. - */ - -static struct pipe_buffer * -vmw_drm_buffer_from_handle(struct drm_api *drm_api, - struct pipe_screen *screen, - const char *name, - unsigned handle) +static struct pipe_texture * +vmw_drm_texture_from_handle(struct drm_api *drm_api, + struct pipe_screen *screen, + struct pipe_texture *templat, + const char *name, + unsigned stride, + unsigned handle) { struct vmw_svga_winsys_surface *vsrf; struct svga_winsys_surface *ssrf; struct vmw_winsys_screen *vws = vmw_winsys_screen(svga_winsys_screen(screen)); - struct pipe_buffer *buf; + struct pipe_texture *tex; union drm_vmw_surface_reference_arg arg; struct drm_vmw_surface_arg *req = &arg.req; struct drm_vmw_surface_create_req *rep = &arg.rep; @@ -282,43 +296,28 @@ vmw_drm_buffer_from_handle(struct drm_api *drm_api, pipe_reference_init(&vsrf->refcnt, 1); p_atomic_set(&vsrf->validated, 0); + vsrf->screen = vws; vsrf->sid = handle; ssrf = svga_winsys_surface(vsrf); - buf = svga_screen_buffer_wrap_surface(screen, rep->format, ssrf); - if (!buf) + tex = svga_screen_texture_wrap_surface(screen, templat, rep->format, ssrf); + if (!tex) vmw_svga_winsys_surface_reference(&vsrf, NULL); - return buf; + return tex; out_mip: vmw_ioctl_surface_destroy(vws, handle); return NULL; } -static struct pipe_texture * -vmw_drm_texture_from_handle(struct drm_api *drm_api, - struct pipe_screen *screen, - struct pipe_texture *templat, - const char *name, - unsigned stride, - unsigned handle) -{ - struct pipe_buffer *buffer; - buffer = vmw_drm_buffer_from_handle(drm_api, screen, name, handle); - - if (!buffer) - return NULL; - - return screen->texture_blanket(screen, templat, &stride, buffer); -} - static boolean -vmw_drm_handle_from_buffer(struct drm_api *drm_api, +vmw_drm_handle_from_texture(struct drm_api *drm_api, struct pipe_screen *screen, - struct pipe_buffer *buffer, + struct pipe_texture *texture, + unsigned *stride, unsigned *handle) { struct svga_winsys_surface *surface = - svga_screen_buffer_get_winsys_surface(buffer); + svga_screen_texture_get_winsys_surface(texture); struct vmw_svga_winsys_surface *vsrf; if (!surface) @@ -326,25 +325,13 @@ vmw_drm_handle_from_buffer(struct drm_api *drm_api, vsrf = vmw_svga_winsys_surface(surface); *handle = vsrf->sid; + *stride = util_format_get_nblocksx(texture->format, texture->width0) * + util_format_get_blocksize(texture->format); + vmw_svga_winsys_surface_reference(&vsrf, NULL); return TRUE; } -static boolean -vmw_drm_handle_from_texture(struct drm_api *drm_api, - struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned *stride, - unsigned *handle) -{ - struct pipe_buffer *buffer; - - if (!svga_screen_buffer_from_texture(texture, &buffer, stride)) - return FALSE; - - return vmw_drm_handle_from_buffer(drm_api, screen, buffer, handle); -} - static struct pipe_context* vmw_drm_create_context(struct drm_api *drm_api, struct pipe_screen *screen) @@ -359,6 +346,7 @@ static struct dri1_api dri1_api_hooks = { static struct drm_api vmw_drm_api_hooks = { .name = "vmwgfx", + .driver_name = "vmwgfx", .create_screen = vmw_drm_create_screen, .create_context = vmw_drm_create_context, .texture_from_shared_handle = vmw_drm_texture_from_handle, diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c index b1c24b0cb6..b9823d7857 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c @@ -53,14 +53,32 @@ vmw_pools_init(struct vmw_winsys_screen *vws) goto error; vws->pools.gmr_mm = mm_bufmgr_create(vws->pools.gmr, - 16*1024*1024, + VMW_GMR_POOL_SIZE, 12 /* 4096 alignment */); if(!vws->pools.gmr_mm) goto error; + /* + * GMR buffers are typically shortlived, but it's possible that at a given + * instance a buffer is mapped. So to avoid stalling we tell pipebuffer to + * forbid creation of buffers beyond half the GMR pool size, + * + * XXX: It is unclear weather we want to limit the total amount of temporary + * malloc memory used to backup unvalidated GMR buffers. On one hand it is + * preferrable to fail an allocation than exhausting the guest memory with + * temporary data, but on the other hand it is possible that a stupid + * application creates large vertex buffers and does not use them for a long + * time -- since the svga pipe driver only emits the DMA uploads when a + * buffer is used for drawing this would effectively disabling swapping GMR + * buffers to memory. So far, the preemptively flush already seems to keep + * total allocated memory within relatively small numbers, so we don't + * limit. + */ vws->pools.gmr_fenced = fenced_bufmgr_create( vws->pools.gmr_mm, - vmw_fence_ops_create(vws)); + vmw_fence_ops_create(vws), + VMW_GMR_POOL_SIZE/2, + ~0); #ifdef DEBUG vws->pools.gmr_fenced = pb_debug_manager_create(vws->pools.gmr_fenced, diff --git a/src/gallium/winsys/drm/vmware/egl/Makefile b/src/gallium/winsys/drm/vmware/egl/Makefile index 8e2980c318..a3e73131c3 100644 --- a/src/gallium/winsys/drm/vmware/egl/Makefile +++ b/src/gallium/winsys/drm/vmware/egl/Makefile @@ -1,18 +1,14 @@ - TOP = ../../../../../.. include $(TOP)/configs/current -LIBNAME = EGL_svga.so +EGL_DRIVER_NAME = vmwgfx +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -PIPE_DRIVERS = \ - $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ +EGL_DRIVER_PIPES = \ $(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/svga/libsvga.a -C_SOURCES = \ - $(COMMON_GALLIUM_SOURCES) - -include ../../Makefile.template - -symlinks: +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/vmware/egl/dummy.c b/src/gallium/winsys/drm/vmware/egl/dummy.c new file mode 100644 index 0000000000..4a1bc28b0b --- /dev/null +++ b/src/gallium/winsys/drm/vmware/egl/dummy.c @@ -0,0 +1 @@ +/* mklib expects at least one object file */ diff --git a/src/gallium/winsys/drm/vmware/egl_g3d/Makefile b/src/gallium/winsys/drm/vmware/egl_g3d/Makefile deleted file mode 100644 index 3cf79924e0..0000000000 --- a/src/gallium/winsys/drm/vmware/egl_g3d/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -TOP = ../../../../../.. -include $(TOP)/configs/current - -EGL_DRIVER_NAME = vmwgfx -EGL_DRIVER_SOURCES = dummy.c -EGL_DRIVER_LIBS = - -EGL_DRIVER_PIPES = \ - $(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \ - $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ - $(TOP)/src/gallium/drivers/trace/libtrace.a \ - $(TOP)/src/gallium/drivers/svga/libsvga.a - -include ../../Makefile.egl_g3d diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_video.c b/src/gallium/winsys/drm/vmware/xorg/vmw_video.c index b065b96346..ff3b992d07 100644 --- a/src/gallium/winsys/drm/vmware/xorg/vmw_video.c +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_video.c @@ -649,7 +649,8 @@ vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, return XvBadAlloc; } - port->currBuf = ++port->currBuf & (VMWARE_VID_NUM_BUFFERS - 1); + if (++(port->currBuf) >= VMWARE_VID_NUM_BUFFERS) + port->currBuf = 0; return Success; } diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c b/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c index 4b208719ca..cd273d091f 100644 --- a/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c @@ -34,10 +34,10 @@ #include "vmw_hook.h" static void vmw_xorg_identify(int flags); -static Bool vmw_xorg_pci_probe(DriverPtr driver, - int entity_num, - struct pci_device *device, - intptr_t match_data); +_X_EXPORT Bool vmw_xorg_pci_probe(DriverPtr driver, + int entity_num, + struct pci_device *device, + intptr_t match_data); static const struct pci_id_match vmw_xorg_device_match[] = { {0x15ad, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0}, @@ -126,7 +126,7 @@ vmw_xorg_identify(int flags) vmw_xorg_chipsets); } -static Bool +_X_EXPORT Bool vmw_xorg_pci_probe(DriverPtr driver, int entity_num, struct pci_device *device, intptr_t match_data) { diff --git a/src/gallium/winsys/egl_xlib/Makefile b/src/gallium/winsys/egl_xlib/Makefile deleted file mode 100644 index 3efb7ed4af..0000000000 --- a/src/gallium/winsys/egl_xlib/Makefile +++ /dev/null @@ -1,89 +0,0 @@ -# src/gallium/winsys/egl_xlib/Makefile - -# Build softpipe/xlib/EGL driver library/object: "egl_softpipe.so" - - -TOP = ../../../.. -include $(TOP)/configs/current - - -DRIVER_NAME = egl_softpipe.so - - -INCLUDE_DIRS = \ - -I$(TOP)/include \ - -I$(TOP)/src/egl/main \ - -I$(TOP)/src/mesa \ - -I$(TOP)/src/mesa/main \ - -I$(TOP)/src/gallium/include \ - -I$(TOP)/src/gallium/drivers \ - -I$(TOP)/src/gallium/auxiliary - -WINSYS_SOURCES = \ - egl_xlib.c \ - sw_winsys.c - -WINSYS_OBJECTS = $(WINSYS_SOURCES:.c=.o) - - -LIBS = \ - $(GALLIUM_DRIVERS) \ - $(GALLIUM_AUXILIARIES) - -# XXX temporary (should create a separate lib with the GL API funcs and -# mesa code, as done for ES 1.x, 2.x, OpenVG, etc) -UNUSED_LIBS = \ - $(TOP)/src/mesa/libglapi.a \ - $(TOP)/src/mesa/libmesagallium.a \ - - -LOCAL_CFLAGS = - - -.c.o: - $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@ - - -.PHONY: library - - -default: depend library Makefile - - -library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) - - -# Make the egl_softpipe.so library -$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(WINSYS_OBJECTS) $(LIBS) - $(TOP)/bin/mklib -o $(DRIVER_NAME) \ - -linker "$(CC)" \ - -noprefix \ - -install $(TOP)/$(LIB_DIR) \ - $(MKLIB_OPTIONS) $(WINSYS_OBJECTS) \ - -Wl,--whole-archive $(LIBS) -Wl,--no-whole-archive - - -depend: $(ALL_SOURCES) - @ echo "running $(MKDEP)" - @ rm -f depend # workaround oops on gutsy?!? - @ touch depend - @ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \ - > /dev/null 2>/dev/null - - -install: default - $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR) - @if [ -e $(TOP)/$(LIB_DIR) ]; then \ - $(MINSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(INSTALL_DIR)/$(LIB_DIR); \ - fi - - -# Emacs tags -tags: - etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h - -clean: - -rm -f *.o *~ *.bak - - -include depend diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c deleted file mode 100644 index 1d9bac3871..0000000000 --- a/src/gallium/winsys/egl_xlib/egl_xlib.c +++ /dev/null @@ -1,853 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * 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. - * - **************************************************************************/ - -/** - * EGL / softpipe / xlib winsys module - * - * Authors: Brian Paul - */ - - -#include <dlfcn.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -#include "pipe/p_compiler.h" -#include "pipe/p_format.h" -#include "pipe/p_state.h" -#include "pipe/internal/p_winsys_screen.h" -#include "util/u_memory.h" -#include "util/u_math.h" -#include "softpipe/sp_winsys.h" -#include "softpipe/sp_texture.h" - -#include "eglconfig.h" -#include "eglconfigutil.h" -#include "eglcontext.h" -#include "egldisplay.h" -#include "egldriver.h" -#include "eglglobals.h" -#include "egllog.h" -#include "eglsurface.h" - -#include "state_tracker/st_public.h" - -#include "sw_winsys.h" - - -/** subclass of _EGLDriver */ -struct xlib_egl_driver -{ - _EGLDriver Base; /**< base class */ - EGLint apis; -}; - - -/** driver data of _EGLDisplay */ -struct xlib_egl_display -{ - Display *Dpy; - - struct pipe_winsys *winsys; - struct pipe_screen *screen; -}; - - -/** subclass of _EGLContext */ -struct xlib_egl_context -{ - _EGLContext Base; /**< base class */ - - struct pipe_context *pipe; /**< Gallium driver context */ - struct st_context *Context; /**< Mesa/gallium state tracker context */ -}; - - -/** subclass of _EGLSurface */ -struct xlib_egl_surface -{ - _EGLSurface Base; /**< base class */ - - /* These are set for window surface */ - Display *Dpy; /**< The X Display of the window */ - Window Win; /**< The user-created window ID */ - GC Gc; - XVisualInfo VisInfo; - - struct pipe_winsys *winsys; - - struct st_framebuffer *Framebuffer; -}; - - -static void -flush_frontbuffer(struct pipe_winsys *pws, - struct pipe_surface *psurf, - void *context_private); - - -/** cast wrapper */ -static INLINE struct xlib_egl_driver * -xlib_egl_driver(_EGLDriver *drv) -{ - return (struct xlib_egl_driver *) drv; -} - - -static INLINE struct xlib_egl_display * -xlib_egl_display(_EGLDisplay *dpy) -{ - return (struct xlib_egl_display *) dpy->DriverData; -} - - -static INLINE struct xlib_egl_surface * -lookup_surface(_EGLSurface *surf) -{ - return (struct xlib_egl_surface *) surf; -} - - -static INLINE struct xlib_egl_context * -lookup_context(_EGLContext *ctx) -{ - return (struct xlib_egl_context *) ctx; -} - - -/** - * Create the EGLConfigs. (one per X visual) - */ -static void -create_configs(struct xlib_egl_display *xdpy, _EGLDisplay *disp) -{ - static const EGLint all_apis = (EGL_OPENGL_ES_BIT | - EGL_OPENGL_ES2_BIT | - EGL_OPENVG_BIT | - EGL_OPENGL_BIT); - XVisualInfo *visInfo, visTemplate; - int num_visuals, i; - - /* get list of all X visuals, create an EGL config for each */ - visTemplate.screen = DefaultScreen(xdpy->Dpy); - visInfo = XGetVisualInfo(xdpy->Dpy, VisualScreenMask, - &visTemplate, &num_visuals); - if (!visInfo) { - printf("egl_xlib.c: couldn't get any X visuals\n"); - abort(); - } - - for (i = 0; i < num_visuals; i++) { - _EGLConfig *config = calloc(1, sizeof(_EGLConfig)); - int id = i + 1; - int rbits = util_bitcount(visInfo[i].red_mask); - int gbits = util_bitcount(visInfo[i].green_mask); - int bbits = util_bitcount(visInfo[i].blue_mask); - int abits = bbits == 8 ? 8 : 0; - int zbits = 24; - int sbits = 8; - int visid = visInfo[i].visualid; -#if defined(__cplusplus) || defined(c_plusplus) - int vistype = visInfo[i].c_class; -#else - int vistype = visInfo[i].class; -#endif - - _eglInitConfig(config, id); - SET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE, rbits + gbits + bbits + abits); - SET_CONFIG_ATTRIB(config, EGL_RED_SIZE, rbits); - SET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE, gbits); - SET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE, bbits); - SET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE, abits); - SET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE, zbits); - SET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE, sbits); - SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_ID, visid); - SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, vistype); - SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_FALSE); - SET_CONFIG_ATTRIB(config, EGL_CONFORMANT, all_apis); - SET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE, all_apis); - SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT); - SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); - SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); - - _eglAddConfig(disp, config); - } - - XFree(visInfo); -} - - -/** - * Called via eglInitialize(), drv->API.Initialize(). - */ -static EGLBoolean -xlib_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, - EGLint *major, EGLint *minor) -{ - struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); - struct xlib_egl_display *xdpy; - - xdpy = CALLOC_STRUCT(xlib_egl_display); - if (!xdpy) - return _eglError(EGL_BAD_ALLOC, "eglInitialize"); - - xdpy->Dpy = (Display *) dpy->NativeDisplay; - if (!xdpy->Dpy) { - xdpy->Dpy = XOpenDisplay(NULL); - if (!xdpy->Dpy) { - free(xdpy); - return EGL_FALSE; - } - } - - /* create winsys and pipe screen */ - xdpy->winsys = create_sw_winsys(); - if (!xdpy->winsys) { - free(xdpy); - return _eglError(EGL_BAD_ALLOC, "eglInitialize"); - } - xdpy->winsys->flush_frontbuffer = flush_frontbuffer; - xdpy->screen = softpipe_create_screen(xdpy->winsys); - if (!xdpy->screen) { - free(xdpy->winsys); - free(xdpy); - return _eglError(EGL_BAD_ALLOC, "eglInitialize"); - } - - dpy->DriverData = (void *) xdpy; - dpy->ClientAPIsMask = xdrv->apis; - - create_configs(xdpy, dpy); - - /* we're supporting EGL 1.4 */ - *major = 1; - *minor = 4; - - return EGL_TRUE; -} - - -/** - * Called via eglTerminate(), drv->API.Terminate(). - */ -static EGLBoolean -xlib_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy) -{ - struct xlib_egl_display *xdpy = xlib_egl_display(dpy); - - _eglReleaseDisplayResources(drv, dpy); - _eglCleanupDisplay(dpy); - - xdpy->screen->destroy(xdpy->screen); - free(xdpy->winsys); - - if (!dpy->NativeDisplay) - XCloseDisplay(xdpy->Dpy); - free(xdpy); - - return EGL_TRUE; -} - - -static _EGLProc -xlib_eglGetProcAddress(_EGLDriver *drv, const char *procname) -{ - return (_EGLProc) st_get_proc_address(procname); -} - - -static void -get_drawable_visual_info(Display *dpy, Drawable d, XVisualInfo *visInfo) -{ - XWindowAttributes attr; - XVisualInfo visTemp, *vis; - int num_visuals; - - XGetWindowAttributes(dpy, d, &attr); - - visTemp.screen = DefaultScreen(dpy); - visTemp.visualid = attr.visual->visualid; - vis = XGetVisualInfo(dpy, - (VisualScreenMask | VisualIDMask), - &visTemp, &num_visuals); - if (vis) - *visInfo = *vis; - - XFree(vis); -} - - - -/** Get size of given window */ -static Status -get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) -{ - Window root; - Status stat; - int xpos, ypos; - unsigned int w, h, bw, depth; - stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); - *width = w; - *height = h; - return stat; -} - - -static void -check_and_update_buffer_size(struct xlib_egl_surface *surface) -{ - uint width, height; - if (surface->Base.Type == EGL_PBUFFER_BIT) { - width = surface->Base.Width; - height = surface->Base.Height; - } - else { - get_drawable_size(surface->Dpy, surface->Win, &width, &height); - } - st_resize_framebuffer(surface->Framebuffer, width, height); - surface->Base.Width = width; - surface->Base.Height = height; -} - - - -static void -display_surface(struct pipe_winsys *pws, - struct pipe_surface *psurf, - struct xlib_egl_surface *xsurf) -{ - struct softpipe_texture *spt = softpipe_texture(psurf->texture); - XImage *ximage; - void *data; - - if (xsurf->Base.Type == EGL_PBUFFER_BIT) - return; - - ximage = XCreateImage(xsurf->Dpy, - xsurf->VisInfo.visual, - xsurf->VisInfo.depth, - ZPixmap, 0, /* format, offset */ - NULL, /* data */ - 0, 0, /* size */ - 32, /* bitmap_pad */ - 0); /* bytes_per_line */ - - - assert(ximage->format); - assert(ximage->bitmap_unit); - - data = pws->buffer_map(pws, spt->buffer, 0); - - /* update XImage's fields */ - ximage->data = data; - ximage->width = psurf->width; - ximage->height = psurf->height; - ximage->bytes_per_line = spt->stride[psurf->level]; - - XPutImage(xsurf->Dpy, xsurf->Win, xsurf->Gc, - ximage, 0, 0, 0, 0, psurf->width, psurf->height); - - XSync(xsurf->Dpy, 0); - - ximage->data = NULL; - XDestroyImage(ximage); - - pws->buffer_unmap(pws, spt->buffer); -} - - - -/** Display gallium surface in X window */ -static void -flush_frontbuffer(struct pipe_winsys *pws, - struct pipe_surface *psurf, - void *context_private) -{ - struct xlib_egl_surface *xsurf = (struct xlib_egl_surface *) context_private; - display_surface(pws, psurf, xsurf); -} - - - -/** - * Called via eglCreateContext(), drv->API.CreateContext(). - */ -static _EGLContext * -xlib_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - _EGLContext *share_list, const EGLint *attrib_list) -{ - struct xlib_egl_display *xdpy = xlib_egl_display(dpy); - struct xlib_egl_context *ctx; - struct st_context *share_ctx = NULL; /* XXX fix */ - __GLcontextModes visual; - - ctx = CALLOC_STRUCT(xlib_egl_context); - if (!ctx) - return NULL; - - /* let EGL lib init the common stuff */ - if (!_eglInitContext(drv, &ctx->Base, conf, attrib_list)) { - free(ctx); - return NULL; - } - - /* API-dependent context creation */ - switch (ctx->Base.ClientAPI) { - case EGL_OPENVG_API: - case EGL_OPENGL_ES_API: - _eglLog(_EGL_DEBUG, "Create Context for ES version %d\n", - ctx->Base.ClientVersion); - /* fall-through */ - case EGL_OPENGL_API: - /* create a softpipe context */ - ctx->pipe = softpipe_create(xdpy->screen); - /* Now do xlib / state tracker inits here */ - _eglConfigToContextModesRec(conf, &visual); - ctx->Context = st_create_context(ctx->pipe, &visual, share_ctx); - break; - default: - _eglError(EGL_BAD_MATCH, "eglCreateContext(unsupported API)"); - free(ctx); - return NULL; - } - - return &ctx->Base; -} - - -static EGLBoolean -xlib_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) -{ - struct xlib_egl_context *context = lookup_context(ctx); - - if (!_eglIsContextBound(&context->Base)) { - /* API-dependent clean-up */ - switch (context->Base.ClientAPI) { - case EGL_OPENGL_ES_API: - case EGL_OPENVG_API: - /* fall-through */ - case EGL_OPENGL_API: - st_destroy_context(context->Context); - break; - default: - assert(0); - } - free(context); - } - return EGL_TRUE; -} - - -/** - * Called via eglMakeCurrent(), drv->API.MakeCurrent(). - */ -static EGLBoolean -xlib_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) -{ - struct xlib_egl_context *context = lookup_context(ctx); - struct xlib_egl_surface *draw_surf = lookup_surface(draw); - struct xlib_egl_surface *read_surf = lookup_surface(read); - struct st_context *oldcontext = NULL; - _EGLContext *oldctx; - - oldctx = _eglGetCurrentContext(); - if (oldctx && _eglIsContextLinked(oldctx)) - oldcontext = st_get_current(); - - if (!_eglMakeCurrent(drv, dpy, draw, read, ctx)) - return EGL_FALSE; - - /* Flush before switching context. Check client API? */ - if (oldcontext) - st_flush(oldcontext, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); - st_make_current((context ? context->Context : NULL), - (draw_surf ? draw_surf->Framebuffer : NULL), - (read_surf ? read_surf->Framebuffer : NULL)); - - if (draw_surf) - check_and_update_buffer_size(draw_surf); - if (read_surf && read_surf != draw_surf) - check_and_update_buffer_size(draw_surf); - - return EGL_TRUE; -} - - -static enum pipe_format -choose_color_format(const __GLcontextModes *visual) -{ - if (visual->redBits == 8 && - visual->greenBits == 8 && - visual->blueBits == 8 && - visual->alphaBits == 8) { - /* XXX this really also depends on the ordering of R,G,B,A */ - return PIPE_FORMAT_A8R8G8B8_UNORM; - } - else { - assert(0); - return PIPE_FORMAT_NONE; - } -} - - -static enum pipe_format -choose_depth_format(const __GLcontextModes *visual) -{ - if (visual->depthBits > 0) - return PIPE_FORMAT_S8Z24_UNORM; - else - return PIPE_FORMAT_NONE; -} - - -static enum pipe_format -choose_stencil_format(const __GLcontextModes *visual) -{ - if (visual->stencilBits > 0) - return PIPE_FORMAT_S8Z24_UNORM; - else - return PIPE_FORMAT_NONE; -} - - -/** - * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). - */ -static _EGLSurface * -xlib_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, - NativeWindowType window, const EGLint *attrib_list) -{ - struct xlib_egl_display *xdpy = xlib_egl_display(disp); - struct xlib_egl_surface *surf; - __GLcontextModes visual; - uint width, height; - - surf = CALLOC_STRUCT(xlib_egl_surface); - if (!surf) - return NULL; - - /* Let EGL lib init the common stuff */ - if (!_eglInitSurface(drv, &surf->Base, EGL_WINDOW_BIT, - conf, attrib_list)) { - free(surf); - return NULL; - } - - /* - * Now init the Xlib and gallium stuff - */ - surf->Win = (Window) window; /* The X window ID */ - surf->Dpy = xdpy->Dpy; /* The X display */ - surf->Gc = XCreateGC(surf->Dpy, surf->Win, 0, NULL); - - surf->winsys = xdpy->winsys; - - _eglConfigToContextModesRec(conf, &visual); - get_drawable_size(surf->Dpy, surf->Win, &width, &height); - get_drawable_visual_info(surf->Dpy, surf->Win, &surf->VisInfo); - - surf->Base.Width = width; - surf->Base.Height = height; - - /* Create GL statetracker framebuffer */ - surf->Framebuffer = st_create_framebuffer(&visual, - choose_color_format(&visual), - choose_depth_format(&visual), - choose_stencil_format(&visual), - width, height, - (void *) surf); - - st_resize_framebuffer(surf->Framebuffer, width, height); - - return &surf->Base; -} - - -static _EGLSurface * -xlib_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, - const EGLint *attrib_list) -{ - struct xlib_egl_display *xdpy = xlib_egl_display(disp); - struct xlib_egl_surface *surf; - __GLcontextModes visual; - uint width, height; - EGLBoolean bind_texture; - - surf = CALLOC_STRUCT(xlib_egl_surface); - if (!surf) { - _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); - return NULL; - } - - if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT, - conf, attrib_list)) { - free(surf); - return NULL; - } - if (surf->Base.Width < 0 || surf->Base.Height < 0) { - _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferSurface"); - free(surf); - return NULL; - } - - bind_texture = (surf->Base.TextureFormat != EGL_NO_TEXTURE); - width = (uint) surf->Base.Width; - height = (uint) surf->Base.Height; - if ((surf->Base.TextureTarget == EGL_NO_TEXTURE && bind_texture) || - (surf->Base.TextureTarget != EGL_NO_TEXTURE && !bind_texture)) { - _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); - free(surf); - return NULL; - } - /* a framebuffer of zero width or height confuses st */ - if (width == 0 || height == 0) { - _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); - free(surf); - return NULL; - } - /* no mipmap generation */ - if (surf->Base.MipmapTexture) { - _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); - free(surf); - return NULL; - } - - surf->winsys = xdpy->winsys; - - _eglConfigToContextModesRec(conf, &visual); - - /* Create GL statetracker framebuffer */ - surf->Framebuffer = st_create_framebuffer(&visual, - choose_color_format(&visual), - choose_depth_format(&visual), - choose_stencil_format(&visual), - width, height, - (void *) surf); - st_resize_framebuffer(surf->Framebuffer, width, height); - - return &surf->Base; -} - - -static EGLBoolean -xlib_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) -{ - struct xlib_egl_surface *surf = lookup_surface(surface); - if (!_eglIsSurfaceBound(&surf->Base)) { - if (surf->Base.Type != EGL_PBUFFER_BIT) - XFreeGC(surf->Dpy, surf->Gc); - st_unreference_framebuffer(surf->Framebuffer); - free(surf); - } - return EGL_TRUE; -} - - -static EGLBoolean -xlib_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLSurface *surface, EGLint buffer) -{ - struct xlib_egl_surface *xsurf = lookup_surface(surface); - struct xlib_egl_context *xctx; - struct pipe_surface *psurf; - enum pipe_format format; - int target; - - if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT) - return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); - if (buffer != EGL_BACK_BUFFER) - return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); - if (xsurf->Base.BoundToTexture) - return _eglError(EGL_BAD_ACCESS, "eglBindTexImage"); - - /* this should be updated when choose_color_format is */ - switch (xsurf->Base.TextureFormat) { - case EGL_TEXTURE_RGB: - format = PIPE_FORMAT_R8G8B8_UNORM; - break; - case EGL_TEXTURE_RGBA: - format = PIPE_FORMAT_A8R8G8B8_UNORM; - break; - default: - return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - } - - switch (xsurf->Base.TextureTarget) { - case EGL_TEXTURE_2D: - target = ST_TEXTURE_2D; - break; - default: - return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - } - - /* flush properly */ - if (eglGetCurrentSurface(EGL_DRAW) == surface) { - xctx = lookup_context(_eglGetCurrentContext()); - st_flush(xctx->Context, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, - NULL); - } - else if (_eglIsSurfaceBound(&xsurf->Base)) { - xctx = lookup_context(xsurf->Base.Binding); - if (xctx) - st_finish(xctx->Context); - } - - st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT, - &psurf); - st_bind_texture_surface(psurf, target, xsurf->Base.MipmapLevel, format); - xsurf->Base.BoundToTexture = EGL_TRUE; - - return EGL_TRUE; -} - - -static EGLBoolean -xlib_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, - EGLint buffer) -{ - struct xlib_egl_surface *xsurf = lookup_surface(surface); - struct pipe_surface *psurf; - - if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT || - !xsurf->Base.BoundToTexture) - return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); - if (buffer != EGL_BACK_BUFFER) - return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); - - st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT, - &psurf); - st_unbind_texture_surface(psurf, ST_TEXTURE_2D, xsurf->Base.MipmapLevel); - xsurf->Base.BoundToTexture = EGL_FALSE; - - return EGL_TRUE; -} - - -static EGLBoolean -xlib_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw) -{ - struct xlib_egl_surface *xsurf = lookup_surface(draw); - struct pipe_winsys *pws = xsurf->winsys; - struct pipe_surface *psurf; - - st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT, - &psurf); - - st_notify_swapbuffers(xsurf->Framebuffer); - - display_surface(pws, psurf, xsurf); - - check_and_update_buffer_size(xsurf); - - return EGL_TRUE; -} - - -/** - * Determine which API(s) is(are) present by looking for some specific - * global symbols. - */ -static EGLint -find_supported_apis(void) -{ - EGLint mask = 0; - void *handle; - - handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); - if(!handle) - return mask; - - if (dlsym(handle, "st_api_OpenGL_ES1")) - mask |= EGL_OPENGL_ES_BIT; - - if (dlsym(handle, "st_api_OpenGL_ES2")) - mask |= EGL_OPENGL_ES2_BIT; - - if (dlsym(handle, "st_api_OpenGL")) - mask |= EGL_OPENGL_BIT; - - if (dlsym(handle, "st_api_OpenVG")) - mask |= EGL_OPENVG_BIT; - - dlclose(handle); - - return mask; -} - - -static void -xlib_Unload(_EGLDriver *drv) -{ - struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); - free(xdrv); -} - - -/** - * This is the main entrypoint into the driver. - * Called by libEGL to instantiate an _EGLDriver object. - */ -_EGLDriver * -_eglMain(const char *args) -{ - struct xlib_egl_driver *xdrv; - - _eglLog(_EGL_INFO, "Entering EGL/Xlib _eglMain(%s)", args); - - xdrv = CALLOC_STRUCT(xlib_egl_driver); - if (!xdrv) - return NULL; - - _eglInitDriverFallbacks(&xdrv->Base); - xdrv->Base.API.Initialize = xlib_eglInitialize; - xdrv->Base.API.Terminate = xlib_eglTerminate; - xdrv->Base.API.GetProcAddress = xlib_eglGetProcAddress; - xdrv->Base.API.CreateContext = xlib_eglCreateContext; - xdrv->Base.API.DestroyContext = xlib_eglDestroyContext; - xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface; - xdrv->Base.API.CreatePbufferSurface = xlib_eglCreatePbufferSurface; - xdrv->Base.API.DestroySurface = xlib_eglDestroySurface; - xdrv->Base.API.BindTexImage = xlib_eglBindTexImage; - xdrv->Base.API.ReleaseTexImage = xlib_eglReleaseTexImage; - xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent; - xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers; - - xdrv->apis = find_supported_apis(); - if (xdrv->apis == 0x0) { - /* the app isn't directly linked with any EGL-supprted APIs - * (such as libGLESv2.so) so use an EGL utility to see what - * APIs might be loaded dynamically on this system. - */ - xdrv->apis = _eglFindAPIs(); - } - - xdrv->Base.Name = "Xlib/softpipe"; - xdrv->Base.Unload = xlib_Unload; - - return &xdrv->Base; -} diff --git a/src/gallium/winsys/egl_xlib/sw_winsys.c b/src/gallium/winsys/egl_xlib/sw_winsys.c deleted file mode 100644 index 6ee3ede38c..0000000000 --- a/src/gallium/winsys/egl_xlib/sw_winsys.c +++ /dev/null @@ -1,231 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * 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. - * - **************************************************************************/ - -/** - * Totally software-based winsys layer. - * Note that the one winsys function that we can't implement here - * is flush_frontbuffer(). - * Whoever uses this code will have to provide that. - * - * Authors: Brian Paul - */ - - -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_state.h" -#include "pipe/p_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" - -#include "sw_winsys.h" - - - -/** Subclass of pipe_winsys */ -struct sw_pipe_winsys -{ - struct pipe_winsys Base; - /* no extra fields for now */ -}; - - -/** subclass of pipe_buffer */ -struct sw_pipe_buffer -{ - struct pipe_buffer Base; - boolean UserBuffer; /** Is this a user-space buffer? */ - void *Data; - void *Mapped; -}; - - -/** cast wrapper */ -static INLINE struct sw_pipe_buffer * -sw_pipe_buffer(struct pipe_buffer *b) -{ - return (struct sw_pipe_buffer *) b; -} - - -static const char * -get_name(struct pipe_winsys *pws) -{ - return "software"; -} - - -/** Create new pipe_buffer and allocate storage of given size */ -static struct pipe_buffer * -buffer_create(struct pipe_winsys *pws, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->Base.reference, 1); - buffer->Base.alignment = alignment; - buffer->Base.usage = usage; - buffer->Base.size = size; - - /* align to 16-byte multiple for Cell */ - buffer->Data = align_malloc(size, MAX2(alignment, 16)); - - return &buffer->Base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) -{ - struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->Base.reference, 1); - buffer->Base.size = bytes; - buffer->UserBuffer = TRUE; - buffer->Data = ptr; - - return &buffer->Base; -} - - -static void * -buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - buffer->Mapped = buffer->Data; - return buffer->Mapped; -} - - -static void -buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - buffer->Mapped = NULL; -} - - -static void -buffer_destroy(struct pipe_buffer *buf) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - - if (buffer->Data && !buffer->UserBuffer) { - align_free(buffer->Data); - buffer->Data = NULL; - } - - free(buffer); -} - - -static struct pipe_buffer * -surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - *stride * nblocksy); -} - - -static void -fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ - /* no-op */ -} - - -static int -fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - /* no-op */ - return 0; -} - - -static int -fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - /* no-op */ - return 0; -} - - -/** - * Create/return a new pipe_winsys object. - */ -struct pipe_winsys * -create_sw_winsys(void) -{ - struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys); - if (!ws) - return NULL; - - /* Fill in this struct with callbacks that pipe will need to - * communicate with the window system, buffer manager, etc. - */ - ws->Base.buffer_create = buffer_create; - ws->Base.user_buffer_create = user_buffer_create; - ws->Base.buffer_map = buffer_map; - ws->Base.buffer_unmap = buffer_unmap; - ws->Base.buffer_destroy = buffer_destroy; - - ws->Base.surface_buffer_create = surface_buffer_create; - - ws->Base.fence_reference = fence_reference; - ws->Base.fence_signalled = fence_signalled; - ws->Base.fence_finish = fence_finish; - - ws->Base.flush_frontbuffer = NULL; /* not implemented here! */ - - ws->Base.get_name = get_name; - - return &ws->Base; -} diff --git a/src/gallium/winsys/egl_xlib/sw_winsys.h b/src/gallium/winsys/egl_xlib/sw_winsys.h deleted file mode 100644 index f96c5a14b0..0000000000 --- a/src/gallium/winsys/egl_xlib/sw_winsys.h +++ /dev/null @@ -1,40 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * 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. - * - **************************************************************************/ - - -#ifndef SW_WINSYS_H -#define SW_WINSYS_H - - -struct pipe_winsys; - - -extern struct pipe_winsys * -create_sw_winsys(void); - - -#endif /* SW_WINSYS_H */ diff --git a/src/gallium/winsys/xlib/xlib.c b/src/gallium/winsys/xlib/xlib.c index 13117712c2..67617a470d 100644 --- a/src/gallium/winsys/xlib/xlib.c +++ b/src/gallium/winsys/xlib/xlib.c @@ -105,3 +105,34 @@ extern void (*linker_foo(const unsigned char *procName))() { return glXGetProcAddress(procName); } + + +/** + * When GLX_INDIRECT_RENDERING is defined, some symbols are missing in + * libglapi.a. We need to define them here. + */ +#ifdef GLX_INDIRECT_RENDERING + +#define GL_GLEXT_PROTOTYPES +#include "GL/gl.h" +#include "glapi/glapi.h" +#include "glapi/glapitable.h" +#include "glapi/glapidispatch.h" + +#if defined(USE_MGL_NAMESPACE) +#define NAME(func) mgl##func +#else +#define NAME(func) gl##func +#endif + +#define DISPATCH(FUNC, ARGS, MESSAGE) \ + CALL_ ## FUNC(GET_DISPATCH(), ARGS); + +#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \ + return CALL_ ## FUNC(GET_DISPATCH(), ARGS); + +/* skip normal ones */ +#define _GLAPI_SKIP_NORMAL_ENTRY_POINTS +#include "glapi/glapitemp.h" + +#endif /* GLX_INDIRECT_RENDERING */ diff --git a/src/gallium/winsys/xlib/xlib_softpipe.c b/src/gallium/winsys/xlib/xlib_softpipe.c index f7c0099584..bf78aca686 100644 --- a/src/gallium/winsys/xlib/xlib_softpipe.c +++ b/src/gallium/winsys/xlib/xlib_softpipe.c @@ -63,7 +63,7 @@ struct xm_buffer XImage *tempImage; #ifdef USE_XSHM - int shm; + boolean shm; /** Is this a shared memory buffer? */ XShmSegmentInfo shminfo; #endif }; @@ -152,7 +152,7 @@ alloc_shm_ximage(struct xm_buffer *b, struct xmesa_buffer *xmb, &b->shminfo, width, height); if (b->tempImage == NULL) { - b->shm = 0; + b->shm = FALSE; return; } @@ -169,12 +169,12 @@ alloc_shm_ximage(struct xm_buffer *b, struct xmesa_buffer *xmb, mesaXErrorFlag = 0; XDestroyImage(b->tempImage); b->tempImage = NULL; - b->shm = 0; + b->shm = FALSE; (void) XSetErrorHandler(old_handler); return; } - b->shm = 1; + b->shm = TRUE; } #endif /* USE_XSHM */ @@ -204,6 +204,14 @@ xm_buffer_destroy(struct pipe_buffer *buf) { struct xm_buffer *oldBuf = xm_buffer(buf); + /* + * Note oldBuf->data may point to one of three things: + * 1. XShm shared memory image data + * 2. User-provided (wrapped) memory, see xm_user_buffer_create() + * 3. Regular, malloc'd memory + * We need to be careful with freeing that data now. + */ + if (oldBuf->data) { #ifdef USE_XSHM if (oldBuf->shminfo.shmid >= 0) { @@ -213,12 +221,20 @@ xm_buffer_destroy(struct pipe_buffer *buf) oldBuf->shminfo.shmid = -1; oldBuf->shminfo.shmaddr = (char *) -1; } - else + + if (oldBuf->shm) { + oldBuf->data = NULL; + } + + if (oldBuf->tempImage) { + XDestroyImage(oldBuf->tempImage); + oldBuf->tempImage = NULL; + } #endif - { - if (!oldBuf->userBuffer) { - align_free(oldBuf->data); - } + + if (oldBuf->data && !oldBuf->userBuffer) { + /* this was regular malloc'd memory */ + align_free(oldBuf->data); } oldBuf->data = NULL; @@ -327,10 +343,8 @@ xm_buffer_create(struct pipe_winsys *pws, buffer->base.usage = usage; buffer->base.size = size; - if (buffer->data == NULL) { - /* align to 16-byte multiple for Cell */ - buffer->data = align_malloc(size, max(alignment, 16)); - } + /* align to 16-byte multiple for Cell */ + buffer->data = align_malloc(size, max(alignment, 16)); return &buffer->base; } |