summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorJosé Fonseca <jfonseca@vmware.com>2010-01-16 23:21:06 +0000
committerJosé Fonseca <jfonseca@vmware.com>2010-01-16 23:21:06 +0000
commitba5d600c90f7075cf2c33a0c5c679ef822e8746e (patch)
treeec6794fba9f2fe563a8bbc03ca06e288b7f51c28 /src/gallium
parentfdfe06ad804ea13e6e436d66c1bcafe0bde2f545 (diff)
parent164fd16cfbc09970676c2e6866e062a5c9b410db (diff)
Merge remote branch 'origin/master' into lp-binning
Conflicts: src/gallium/drivers/llvmpipe/lp_quad.h src/gallium/drivers/llvmpipe/lp_setup.c
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/auxiliary/Makefile1
-rw-r--r--src/gallium/auxiliary/SConscript1
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c1
-rw-r--r--src/gallium/auxiliary/draw/draw_context.h8
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.c9
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_clip.c38
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_vbuf.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h5
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c29
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h3
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_emit.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch.c45
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c5
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c14
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.c8
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.h1
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_ppc.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_varient.c10
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c282
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_x86sse.c7
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_x86sse.h1
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_dump.c3
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c8
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ppc.c3
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sanity.c6
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sse2.c50
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ureg.c84
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ureg.h34
-rw-r--r--src/gallium/auxiliary/translate/translate.h18
-rw-r--r--src/gallium/auxiliary/translate/translate_generic.c40
-rw-r--r--src/gallium/auxiliary/translate/translate_sse.c186
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c168
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.c1
-rw-r--r--src/gallium/auxiliary/util/u_format.csv8
-rw-r--r--src/gallium/auxiliary/util/u_pack_color.h2
-rw-r--r--src/gallium/auxiliary/util/u_ringbuffer.c145
-rw-r--r--src/gallium/auxiliary/util/u_ringbuffer.h29
-rw-r--r--src/gallium/auxiliary/util/u_tile.c5
-rw-r--r--src/gallium/auxiliary/vl/vl_compositor.c22
-rw-r--r--src/gallium/auxiliary/vl/vl_compositor.h2
-rw-r--r--src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c28
-rw-r--r--src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h4
-rw-r--r--src/gallium/docs/source/context.rst66
-rw-r--r--src/gallium/docs/source/distro.rst8
-rw-r--r--src/gallium/drivers/cell/common.h3
-rw-r--r--src/gallium/drivers/cell/ppu/cell_context.h10
-rw-r--r--src/gallium/drivers/cell/ppu/cell_draw_arrays.c12
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_emit.c6
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_shader.c4
-rw-r--r--src/gallium/drivers/cell/spu/spu_command.c5
-rw-r--r--src/gallium/drivers/cell/spu/spu_exec.c6
-rw-r--r--src/gallium/drivers/cell/spu/spu_exec.h4
-rw-r--r--src/gallium/drivers/cell/spu/spu_funcs.c2
-rw-r--r--src/gallium/drivers/cell/spu/spu_main.h22
-rw-r--r--src/gallium/drivers/cell/spu/spu_render.c2
-rw-r--r--src/gallium/drivers/cell/spu/spu_vertex_fetch.c5
-rw-r--r--src/gallium/drivers/cell/spu/spu_vertex_shader.c15
-rw-r--r--src/gallium/drivers/failover/fo_context.h2
-rw-r--r--src/gallium/drivers/failover/fo_state.c2
-rw-r--r--src/gallium/drivers/i915/i915_context.h3
-rw-r--r--src/gallium/drivers/i915/i915_state.c12
-rw-r--r--src/gallium/drivers/i965/brw_pipe_shader.c6
-rw-r--r--src/gallium/drivers/identity/id_context.c12
-rw-r--r--src/gallium/drivers/llvmpipe/README39
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_misc.cpp14
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.c4
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h4
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_derived.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c11
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_blend.c22
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_conv.c6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_format.c2
-rw-r--r--src/gallium/drivers/nv04/nv04_state.c12
-rw-r--r--src/gallium/drivers/nv10/nv10_state.c12
-rw-r--r--src/gallium/drivers/nv20/nv20_state.c12
-rw-r--r--src/gallium/drivers/nv30/nv30_fragtex.c10
-rw-r--r--src/gallium/drivers/nv30/nv30_state.c6
-rw-r--r--src/gallium/drivers/nv40/nv40_state.c6
-rw-r--r--src/gallium/drivers/nv50/nv50_context.c8
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h17
-rw-r--r--src/gallium/drivers/nv50/nv50_miptree.c17
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c1060
-rw-r--r--src/gallium/drivers/nv50/nv50_program.h20
-rw-r--r--src/gallium/drivers/nv50/nv50_query.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.c42
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.h4
-rw-r--r--src/gallium/drivers/nv50/nv50_state.c50
-rw-r--r--src/gallium/drivers/nv50/nv50_state_validate.c26
-rw-r--r--src/gallium/drivers/nv50/nv50_tex.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_vbo.c8
-rw-r--r--src/gallium/drivers/r300/r300_blit.c6
-rw-r--r--src/gallium/drivers/r300/r300_chipset.c10
-rw-r--r--src/gallium/drivers/r300/r300_chipset.h9
-rw-r--r--src/gallium/drivers/r300/r300_context.c48
-rw-r--r--src/gallium/drivers/r300/r300_context.h73
-rw-r--r--src/gallium/drivers/r300/r300_cs.h2
-rw-r--r--src/gallium/drivers/r300/r300_emit.c250
-rw-r--r--src/gallium/drivers/r300/r300_emit.h22
-rw-r--r--src/gallium/drivers/r300/r300_flush.c10
-rw-r--r--src/gallium/drivers/r300/r300_reg.h16
-rw-r--r--src/gallium/drivers/r300/r300_render.c143
-rw-r--r--src/gallium/drivers/r300/r300_state.c141
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c41
-rw-r--r--src/gallium/drivers/r300/r300_state_invariant.c4
-rw-r--r--src/gallium/drivers/r300/r300_texture.c62
-rw-r--r--src/gallium/drivers/softpipe/sp_context.c6
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h2
-rw-r--r--src/gallium/drivers/softpipe/sp_draw_arrays.c198
-rw-r--r--src/gallium/drivers/softpipe/sp_state.h20
-rw-r--r--src/gallium/drivers/softpipe/sp_state_fs.c5
-rw-r--r--src/gallium/drivers/svga/svga_pipe_constants.c4
-rw-r--r--src/gallium/drivers/svga/svga_state_fs.c6
-rw-r--r--src/gallium/drivers/svga/svga_state_vs.c10
-rw-r--r--src/gallium/drivers/trace/tr_context.c11
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.c4
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.h2
-rw-r--r--src/gallium/include/pipe/p_compiler.h86
-rw-r--r--src/gallium/include/pipe/p_context.h18
-rw-r--r--src/gallium/include/pipe/p_screen.h5
-rw-r--r--src/gallium/include/pipe/p_shader_tokens.h23
-rw-r--r--src/gallium/include/pipe/p_state.h18
-rw-r--r--src/gallium/include/state_tracker/drm_api.h2
-rw-r--r--src/gallium/state_trackers/dri/dri_drawable.c10
-rw-r--r--src/gallium/state_trackers/dri/dri_drawable.h3
-rw-r--r--src/gallium/state_trackers/dri/dri_screen.c1
-rw-r--r--src/gallium/state_trackers/egl_g3d/Makefile72
-rw-r--r--src/gallium/state_trackers/egl_g3d/common/egl_g3d.c1147
-rw-r--r--src/gallium/state_trackers/egl_g3d/common/egl_g3d.h127
-rw-r--r--src/gallium/state_trackers/egl_g3d/common/egl_st.c131
-rw-r--r--src/gallium/state_trackers/egl_g3d/common/egl_st.h73
-rw-r--r--src/gallium/state_trackers/egl_g3d/common/native.h220
-rw-r--r--src/gallium/state_trackers/egl_g3d/common/st_public_tmp.h20
-rw-r--r--src/gallium/state_trackers/egl_g3d/kms/native_kms.c855
-rw-r--r--src/gallium/state_trackers/egl_g3d/kms/native_kms.h139
-rw-r--r--src/gallium/state_trackers/egl_g3d/x11/glxinit.c573
-rw-r--r--src/gallium/state_trackers/egl_g3d/x11/glxinit.h14
-rw-r--r--src/gallium/state_trackers/egl_g3d/x11/native_dri2.c690
-rw-r--r--src/gallium/state_trackers/egl_g3d/x11/native_x11.c72
-rw-r--r--src/gallium/state_trackers/egl_g3d/x11/native_x11.h37
-rw-r--r--src/gallium/state_trackers/egl_g3d/x11/native_ximage.c676
-rw-r--r--src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c231
-rw-r--r--src/gallium/state_trackers/egl_g3d/x11/sw_winsys.h40
-rw-r--r--src/gallium/state_trackers/egl_g3d/x11/x11_screen.c402
-rw-r--r--src/gallium/state_trackers/egl_g3d/x11/x11_screen.h99
-rw-r--r--src/gallium/state_trackers/glx/xlib/glx_api.c152
-rw-r--r--src/gallium/state_trackers/glx/xlib/glx_getproc.c2
-rw-r--r--src/gallium/state_trackers/glx/xlib/glx_usefont.c3
-rw-r--r--src/gallium/state_trackers/python/SConscript27
-rw-r--r--src/gallium/state_trackers/python/gallium.i1
-rw-r--r--src/gallium/state_trackers/python/p_context.i5
-rw-r--r--src/gallium/state_trackers/python/p_device.i10
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/interpreter.py8
-rw-r--r--src/gallium/state_trackers/python/samples/gs.py4
-rw-r--r--src/gallium/state_trackers/python/samples/tri.py4
-rw-r--r--src/gallium/state_trackers/python/st_llvmpipe_winsys.c148
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/.gitignore1
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py2
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/.gitignore1
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py2
-rw-r--r--src/gallium/state_trackers/vega/api_filters.c16
-rw-r--r--src/gallium/state_trackers/vega/mask.c32
-rw-r--r--src/gallium/state_trackers/vega/paint.c3
-rw-r--r--src/gallium/state_trackers/vega/polygon.c1
-rw-r--r--src/gallium/state_trackers/vega/shader.c16
-rw-r--r--src/gallium/state_trackers/vega/vg_context.c24
-rw-r--r--src/gallium/state_trackers/vega/vg_context.h6
-rw-r--r--src/gallium/state_trackers/vega/vg_tracker.c15
-rw-r--r--src/gallium/state_trackers/vega/vg_tracker.h26
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.c28
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.h4
-rw-r--r--src/gallium/state_trackers/xorg/xorg_xv.c9
-rw-r--r--src/gallium/winsys/drm/Makefile.egl_g3d64
-rw-r--r--src/gallium/winsys/drm/i965/egl_g3d/Makefile14
-rw-r--r--src/gallium/winsys/drm/i965/egl_g3d/dummy.c1
-rw-r--r--src/gallium/winsys/drm/i965/gem/i965_drm_api.c1
-rw-r--r--src/gallium/winsys/drm/i965/xorg/Makefile59
-rw-r--r--src/gallium/winsys/drm/intel/egl_g3d/Makefile14
-rw-r--r--src/gallium/winsys/drm/intel/egl_g3d/dummy.c1
-rw-r--r--src/gallium/winsys/drm/intel/gem/intel_drm_api.c1
-rw-r--r--src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c3
-rw-r--r--src/gallium/winsys/drm/nouveau/egl_g3d/Makefile19
-rw-r--r--src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c1
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_buffer.c64
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_drm.c1
-rw-r--r--src/gallium/winsys/drm/radeon/dri/Makefile2
-rw-r--r--src/gallium/winsys/drm/radeon/egl_g3d/Makefile14
-rw-r--r--src/gallium/winsys/drm/radeon/egl_g3d/dummy.c1
-rw-r--r--src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c1
-rw-r--r--src/gallium/winsys/drm/vmware/egl_g3d/Makefile14
-rw-r--r--src/gallium/winsys/drm/vmware/egl_g3d/dummy.c1
-rw-r--r--src/gallium/winsys/egl_xlib/egl_xlib.c24
-rw-r--r--src/gallium/winsys/xlib/xlib.c2
194 files changed, 9142 insertions, 1560 deletions
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index e3af41c6e04..8f937e3b4e9 100644
--- a/src/gallium/auxiliary/Makefile
+++ b/src/gallium/auxiliary/Makefile
@@ -111,6 +111,7 @@ C_SOURCES = \
util/u_math.c \
util/u_mm.c \
util/u_rect.c \
+ util/u_ringbuffer.c \
util/u_simple_shaders.c \
util/u_snprintf.c \
util/u_stream_stdc.c \
diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript
index 782eb533863..f957090b5fb 100644
--- a/src/gallium/auxiliary/SConscript
+++ b/src/gallium/auxiliary/SConscript
@@ -147,6 +147,7 @@ source = [
'util/u_math.c',
'util/u_mm.c',
'util/u_rect.c',
+ 'util/u_ringbuffer.c',
'util/u_simple_shaders.c',
'util/u_snprintf.c',
'util/u_stream_stdc.c',
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 667aa46b208..e90dfc5aec4 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -95,6 +95,7 @@ void draw_destroy( struct draw_context *draw )
draw_pipeline_destroy( draw );
draw_pt_destroy( draw );
draw_vs_destroy( draw );
+ draw_gs_destroy( draw );
FREE( draw );
}
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index b716209df29..8a64c06efcd 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -164,6 +164,14 @@ void draw_set_mapped_constant_buffer(struct draw_context *draw,
void draw_arrays(struct draw_context *draw, unsigned prim,
unsigned start, unsigned count);
+void
+draw_arrays_instanced(struct draw_context *draw,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount);
+
void draw_flush(struct draw_context *draw);
diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
index 5db2e755423..daf8d071f12 100644
--- a/src/gallium/auxiliary/draw/draw_gs.c
+++ b/src/gallium/auxiliary/draw/draw_gs.c
@@ -59,6 +59,15 @@ draw_gs_init( struct draw_context *draw )
return TRUE;
}
+void draw_gs_destroy( struct draw_context *draw )
+{
+ if (!draw->gs.machine)
+ return;
+
+ align_free(draw->gs.machine->Primitives);
+
+ tgsi_exec_machine_destroy(draw->gs.machine);
+}
void draw_gs_set_constants( struct draw_context *draw,
const float (*constants)[4],
diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c
index 205cda5eabe..51a6115ebf5 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_clip.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c
@@ -55,7 +55,7 @@
-struct clipper {
+struct clip_stage {
struct draw_stage stage; /**< base class */
/* Basically duplicate some of the flatshading logic here:
@@ -70,9 +70,9 @@ struct clipper {
/* This is a bit confusing:
*/
-static INLINE struct clipper *clipper_stage( struct draw_stage *stage )
+static INLINE struct clip_stage *clip_stage( struct draw_stage *stage )
{
- return (struct clipper *)stage;
+ return (struct clip_stage *)stage;
}
@@ -92,11 +92,12 @@ static void interp_attr( float *fdst,
fdst[3] = LINTERP( t, fout[3], fin[3] );
}
+
static void copy_colors( struct draw_stage *stage,
struct vertex_header *dst,
const struct vertex_header *src )
{
- const struct clipper *clipper = clipper_stage(stage);
+ const struct clip_stage *clipper = clip_stage(stage);
uint i;
for (i = 0; i < clipper->num_color_attribs; i++) {
const uint attr = clipper->color_attribs[i];
@@ -108,7 +109,7 @@ static void copy_colors( struct draw_stage *stage,
/* Interpolate between two vertices to produce a third.
*/
-static void interp( const struct clipper *clip,
+static void interp( const struct clip_stage *clip,
struct vertex_header *dst,
float t,
const struct vertex_header *out,
@@ -179,7 +180,7 @@ static void emit_poly( struct draw_stage *stage,
header.v[2] = inlist[0]; /* keep in v[2] for flatshading */
if (i == n-1)
- header.flags |= edge_last;
+ header.flags |= edge_last;
if (0) {
const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
@@ -200,13 +201,14 @@ static void emit_poly( struct draw_stage *stage,
}
}
+
static INLINE float
dot4(const float *a, const float *b)
{
- return (a[0]*b[0] +
- a[1]*b[1] +
- a[2]*b[2] +
- a[3]*b[3]);
+ return (a[0] * b[0] +
+ a[1] * b[1] +
+ a[2] * b[2] +
+ a[3] * b[3]);
}
@@ -217,7 +219,7 @@ do_clip_tri( struct draw_stage *stage,
struct prim_header *header,
unsigned clipmask )
{
- struct clipper *clipper = clipper_stage( stage );
+ struct clip_stage *clipper = clip_stage( stage );
struct vertex_header *a[MAX_CLIPPED_VERTICES];
struct vertex_header *b[MAX_CLIPPED_VERTICES];
struct vertex_header **inlist = a;
@@ -280,6 +282,7 @@ do_clip_tri( struct draw_stage *stage,
dp_prev = dp;
}
+ /* swap in/out lists */
{
struct vertex_header **tmp = inlist;
inlist = outlist;
@@ -291,15 +294,11 @@ do_clip_tri( struct draw_stage *stage,
/* If flat-shading, copy color to new provoking vertex.
*/
if (clipper->flat && inlist[0] != header->v[2]) {
- if (1) {
- inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
- }
+ inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
copy_colors(stage, inlist[0], header->v[2]);
}
-
-
/* Emit the polygon as triangles to the setup stage:
*/
if (n >= 3)
@@ -314,7 +313,7 @@ do_clip_line( struct draw_stage *stage,
struct prim_header *header,
unsigned clipmask )
{
- const struct clipper *clipper = clipper_stage( stage );
+ const struct clip_stage *clipper = clip_stage( stage );
struct vertex_header *v0 = header->v[0];
struct vertex_header *v1 = header->v[1];
const float *pos0 = v0->clip;
@@ -416,13 +415,14 @@ clip_tri( struct draw_stage *stage,
}
}
+
/* Update state. Could further delay this until we hit the first
* primitive that really requires clipping.
*/
static void
clip_init_state( struct draw_stage *stage )
{
- struct clipper *clipper = clipper_stage( stage );
+ struct clip_stage *clipper = clip_stage( stage );
clipper->flat = stage->draw->rasterizer->flatshade ? TRUE : FALSE;
@@ -488,7 +488,7 @@ static void clip_destroy( struct draw_stage *stage )
*/
struct draw_stage *draw_clip_stage( struct draw_context *draw )
{
- struct clipper *clipper = CALLOC_STRUCT(clipper);
+ struct clip_stage *clipper = CALLOC_STRUCT(clip_stage);
if (clipper == NULL)
goto fail;
diff --git a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
index 1a5269c0de9..d40c0352401 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
@@ -138,7 +138,7 @@ emit_vertex( struct vbuf_stage *vbuf,
/* Note: we really do want data[0] here, not data[pos]:
*/
vbuf->translate->set_buffer(vbuf->translate, 0, vertex->data[0], 0);
- vbuf->translate->run(vbuf->translate, 0, 1, vbuf->vertex_ptr);
+ vbuf->translate->run(vbuf->translate, 0, 1, 0, vbuf->vertex_ptr);
if (0) draw_dump_emitted_vertex(vbuf->vinfo, (uint8_t *)vbuf->vertex_ptr);
@@ -271,10 +271,12 @@ vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
emit_sz = 0;
break;
}
-
+
+ hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
hw_key.element[i].input_buffer = src_buffer;
hw_key.element[i].input_offset = src_offset;
+ hw_key.element[i].instance_divisor = 0;
hw_key.element[i].output_format = output_format;
hw_key.element[i].output_offset = dst_offset;
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index e49041556bd..ef49e575366 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -172,6 +172,8 @@ struct draw_context
boolean force_passthrough; /**< never clip or shade */
+ boolean dump_vs;
+
double mrd; /**< minimum resolvable depth value, for polygon offset */
/* pipe state that we need: */
@@ -239,6 +241,8 @@ struct draw_context
unsigned reduced_prim;
+ unsigned instance_id;
+
void *driver_private;
};
@@ -265,6 +269,7 @@ 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_destroy( struct draw_context *draw );
/*******************************************************************************
* Common shading code:
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 2801dbafe47..a5ddec52863 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -280,20 +280,33 @@ void
draw_arrays(struct draw_context *draw, unsigned prim,
unsigned start, unsigned count)
{
- unsigned reduced_prim = u_reduced_prim(prim);
+ draw_arrays_instanced(draw, prim, start, count, 0, 1);
+}
+
+void
+draw_arrays_instanced(struct draw_context *draw,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount)
+{
+ unsigned reduced_prim = u_reduced_prim(mode);
+ unsigned instance;
+
if (reduced_prim != draw->reduced_prim) {
- draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);
draw->reduced_prim = reduced_prim;
}
if (0)
- draw_print_arrays(draw, prim, start, MIN2(count, 20));
+ draw_print_arrays(draw, mode, start, MIN2(count, 20));
#if 0
{
int i;
- debug_printf("draw_arrays(prim=%u start=%u count=%u):\n",
- prim, start, count);
+ debug_printf("draw_arrays(mode=%u start=%u count=%u):\n",
+ mode, start, count);
tgsi_dump(draw->vs.vertex_shader->state.tokens, 0);
debug_printf("Elements:\n");
for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
@@ -311,6 +324,8 @@ draw_arrays(struct draw_context *draw, unsigned prim,
}
#endif
- /* drawing done here: */
- draw_pt_arrays(draw, prim, start, count);
+ for (instance = 0; instance < instanceCount; instance++) {
+ draw->instance_id = instance + startInstance;
+ draw_pt_arrays(draw, mode, start, count);
+ }
}
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index 20edf7a227e..d5e0d92a605 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -183,7 +183,8 @@ struct pt_emit *draw_pt_emit_create( struct draw_context *draw );
struct pt_fetch;
void draw_pt_fetch_prepare( struct pt_fetch *fetch,
unsigned vertex_input_count,
- unsigned vertex_size );
+ unsigned vertex_size,
+ unsigned instance_id_index );
void draw_pt_fetch_run( struct pt_fetch *fetch,
const unsigned *elts,
diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c
index 064e16c295c..4fb53276bbe 100644
--- a/src/gallium/auxiliary/draw/draw_pt_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_emit.c
@@ -121,10 +121,12 @@ void draw_pt_emit_prepare( struct pt_emit *emit,
emit_sz = 0;
break;
}
-
+
+ hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
hw_key.element[i].input_buffer = src_buffer;
hw_key.element[i].input_offset = src_offset;
+ hw_key.element[i].instance_divisor = 0;
hw_key.element[i].output_format = output_format;
hw_key.element[i].output_offset = dst_offset;
@@ -204,6 +206,7 @@ void draw_pt_emit( struct pt_emit *emit,
translate->run( translate,
0,
vertex_count,
+ draw->instance_id,
hw_verts );
render->unmap_vertices( render,
@@ -263,6 +266,7 @@ void draw_pt_emit_linear(struct pt_emit *emit,
translate->run(translate,
0,
count,
+ draw->instance_id,
hw_verts);
if (0) {
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c
index 305bfef4352..55e7a7b81ad 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c
@@ -58,12 +58,14 @@ struct pt_fetch {
*/
void draw_pt_fetch_prepare( struct pt_fetch *fetch,
unsigned vs_input_count,
- unsigned vertex_size )
+ unsigned vertex_size,
+ unsigned instance_id_index )
{
struct draw_context *draw = fetch->draw;
unsigned nr_inputs;
- unsigned i, nr = 0;
+ unsigned i, nr = 0, ei = 0;
unsigned dst_offset = 0;
+ unsigned num_extra_inputs = 0;
struct translate_key key;
fetch->vertex_size = vertex_size;
@@ -78,9 +80,11 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
{
/* Need to set header->vertex_id = 0xffff somehow.
*/
+ key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
key.element[nr].input_format = PIPE_FORMAT_R32_FLOAT;
key.element[nr].input_buffer = draw->pt.nr_vertex_buffers;
key.element[nr].input_offset = 0;
+ key.element[nr].instance_divisor = 0;
key.element[nr].output_format = PIPE_FORMAT_R32_FLOAT;
key.element[nr].output_offset = dst_offset;
dst_offset += 1 * sizeof(float);
@@ -91,19 +95,36 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
*/
dst_offset += 4 * sizeof(float);
}
-
- assert( draw->pt.nr_vertex_elements >= vs_input_count );
- nr_inputs = MIN2( vs_input_count, draw->pt.nr_vertex_elements );
+ if (instance_id_index != ~0) {
+ num_extra_inputs++;
+ }
+
+ assert(draw->pt.nr_vertex_elements + num_extra_inputs >= vs_input_count);
+
+ nr_inputs = MIN2(vs_input_count, draw->pt.nr_vertex_elements + num_extra_inputs);
for (i = 0; i < nr_inputs; i++) {
- key.element[nr].input_format = draw->pt.vertex_element[i].src_format;
- key.element[nr].input_buffer = draw->pt.vertex_element[i].vertex_buffer_index;
- key.element[nr].input_offset = draw->pt.vertex_element[i].src_offset;
- key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
- key.element[nr].output_offset = dst_offset;
+ if (i == instance_id_index) {
+ key.element[nr].type = TRANSLATE_ELEMENT_INSTANCE_ID;
+ key.element[nr].input_format = PIPE_FORMAT_R32_USCALED;
+ key.element[nr].output_format = PIPE_FORMAT_R32_USCALED;
+ key.element[nr].output_offset = dst_offset;
+
+ dst_offset += sizeof(uint);
+ } else {
+ key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
+ key.element[nr].input_format = draw->pt.vertex_element[ei].src_format;
+ key.element[nr].input_buffer = draw->pt.vertex_element[ei].vertex_buffer_index;
+ key.element[nr].input_offset = draw->pt.vertex_element[ei].src_offset;
+ key.element[nr].instance_divisor = draw->pt.vertex_element[ei].instance_divisor;
+ key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ key.element[nr].output_offset = dst_offset;
+
+ ei++;
+ dst_offset += 4 * sizeof(float);
+ }
- dst_offset += 4 * sizeof(float);
nr++;
}
@@ -158,6 +179,7 @@ void draw_pt_fetch_run( struct pt_fetch *fetch,
translate->run_elts( translate,
elts,
count,
+ draw->instance_id,
verts );
}
@@ -183,6 +205,7 @@ void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
translate->run( translate,
start,
count,
+ draw->instance_id,
verts );
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index e7fe6b3b768..2a604470e9a 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -166,9 +166,11 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
continue;
}
+ key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
key.element[i].input_format = input_format;
key.element[i].input_buffer = input_buffer;
key.element[i].input_offset = input_offset;
+ key.element[i].instance_divisor = src->instance_divisor;
key.element[i].output_format = output_format;
key.element[i].output_offset = dst_offset;
@@ -256,6 +258,7 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
feme->translate->run_elts( feme->translate,
fetch_elts,
fetch_count,
+ draw->instance_id,
hw_verts );
if (0) {
@@ -314,6 +317,7 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
feme->translate->run( feme->translate,
start,
count,
+ draw->instance_id,
hw_verts );
if (0) {
@@ -374,6 +378,7 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
feme->translate->run( feme->translate,
start,
count,
+ draw->instance_id,
hw_verts );
draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) );
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 1a9df4cac5d..23da556f797 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -59,6 +59,8 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_context *draw = fpme->draw;
struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+ unsigned i;
+ unsigned instance_id_index = ~0;
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
@@ -66,6 +68,15 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
unsigned nr = MAX2( vs->info.num_inputs,
vs->info.num_outputs + 1 );
+ /* Scan for instanceID system value.
+ */
+ for (i = 0; i < vs->info.num_inputs; i++) {
+ if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
+ instance_id_index = i;
+ break;
+ }
+ }
+
fpme->prim = prim;
fpme->opt = opt;
@@ -79,7 +90,8 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
draw_pt_fetch_prepare( fpme->fetch,
vs->info.num_inputs,
- fpme->vertex_size );
+ fpme->vertex_size,
+ instance_id_index );
/* XXX: it's not really gl rasterization rules we care about here,
* but gl vs dx9 clip spaces.
*/
diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c
index 35536895326..e03ac8c2291 100644
--- a/src/gallium/auxiliary/draw/draw_vs.c
+++ b/src/gallium/auxiliary/draw/draw_vs.c
@@ -43,11 +43,11 @@
#include "translate/translate.h"
#include "translate/translate_cache.h"
+#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_exec.h"
-
void draw_vs_set_constants( struct draw_context *draw,
const float (*constants)[4],
unsigned size )
@@ -83,6 +83,10 @@ draw_create_vertex_shader(struct draw_context *draw,
{
struct draw_vertex_shader *vs;
+ if (draw->dump_vs) {
+ tgsi_dump(shader->tokens, 0);
+ }
+
vs = draw_create_vs_llvm( draw, shader );
if (!vs) {
vs = draw_create_vs_sse( draw, shader );
@@ -152,6 +156,8 @@ draw_delete_vertex_shader(struct draw_context *draw,
boolean
draw_vs_init( struct draw_context *draw )
{
+ draw->dump_vs = debug_get_bool_option("GALLIUM_DUMP_VS", FALSE);
+
draw->vs.machine = tgsi_exec_machine_create();
if (!draw->vs.machine)
return FALSE;
diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h
index e3b807ebd0e..00036cfe68b 100644
--- a/src/gallium/auxiliary/draw/draw_vs.h
+++ b/src/gallium/auxiliary/draw/draw_vs.h
@@ -43,6 +43,7 @@ struct draw_varient_input
enum pipe_format format;
unsigned buffer;
unsigned offset;
+ unsigned instance_divisor;
};
struct draw_varient_output
diff --git a/src/gallium/auxiliary/draw/draw_vs_ppc.c b/src/gallium/auxiliary/draw/draw_vs_ppc.c
index ad184bd696d..da9f3e3d35c 100644
--- a/src/gallium/auxiliary/draw/draw_vs_ppc.c
+++ b/src/gallium/auxiliary/draw/draw_vs_ppc.c
@@ -98,9 +98,9 @@ vs_ppc_run_linear( struct draw_vertex_shader *base,
/* loop over verts */
for (i = 0; i < count; i += MAX_VERTICES) {
const uint max_vertices = MIN2(MAX_VERTICES, count - i);
- float inputs_soa[PIPE_MAX_SHADER_INPUTS][4][4] ALIGN16_ATTRIB;
- float outputs_soa[PIPE_MAX_SHADER_OUTPUTS][4][4] ALIGN16_ATTRIB;
- float temps_soa[TGSI_EXEC_NUM_TEMPS][4][4] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) float inputs_soa[PIPE_MAX_SHADER_INPUTS][4][4];
+ PIPE_ALIGN_VAR(16) float outputs_soa[PIPE_MAX_SHADER_OUTPUTS][4][4];
+ PIPE_ALIGN_VAR(16) float temps_soa[TGSI_EXEC_NUM_TEMPS][4][4];
uint attr;
/* convert (up to) four input verts to SoA format */
diff --git a/src/gallium/auxiliary/draw/draw_vs_varient.c b/src/gallium/auxiliary/draw/draw_vs_varient.c
index d16692584e5..9f40030f39f 100644
--- a/src/gallium/auxiliary/draw/draw_vs_varient.c
+++ b/src/gallium/auxiliary/draw/draw_vs_varient.c
@@ -142,6 +142,7 @@ static void PIPE_CDECL vsvg_run_elts( struct draw_vs_varient *varient,
vsvg->fetch->run_elts( vsvg->fetch,
elts,
count,
+ vsvg->draw->instance_id,
temp_buffer );
vsvg->base.vs->run_linear( vsvg->base.vs,
@@ -181,6 +182,7 @@ static void PIPE_CDECL vsvg_run_elts( struct draw_vs_varient *varient,
vsvg->emit->run( vsvg->emit,
0, count,
+ vsvg->draw->instance_id,
output_buffer );
FREE(temp_buffer);
@@ -203,6 +205,7 @@ static void PIPE_CDECL vsvg_run_linear( struct draw_vs_varient *varient,
vsvg->fetch->run( vsvg->fetch,
start,
count,
+ vsvg->draw->instance_id,
temp_buffer );
vsvg->base.vs->run_linear( vsvg->base.vs,
@@ -239,6 +242,7 @@ static void PIPE_CDECL vsvg_run_linear( struct draw_vs_varient *varient,
vsvg->emit->run( vsvg->emit,
0, count,
+ vsvg->draw->instance_id,
output_buffer );
FREE(temp_buffer);
@@ -281,9 +285,11 @@ struct draw_vs_varient *draw_vs_varient_generic( struct draw_vertex_shader *vs,
fetch.nr_elements = key->nr_inputs;
fetch.output_stride = vsvg->temp_vertex_stride;
for (i = 0; i < key->nr_inputs; i++) {
+ fetch.element[i].type = TRANSLATE_ELEMENT_NORMAL;
fetch.element[i].input_format = key->element[i].in.format;
fetch.element[i].input_buffer = key->element[i].in.buffer;
fetch.element[i].input_offset = key->element[i].in.offset;
+ fetch.element[i].instance_divisor = 0;
fetch.element[i].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
fetch.element[i].output_offset = i * 4 * sizeof(float);
assert(fetch.element[i].output_offset < fetch.output_stride);
@@ -295,17 +301,21 @@ struct draw_vs_varient *draw_vs_varient_generic( struct draw_vertex_shader *vs,
for (i = 0; i < key->nr_outputs; i++) {
if (key->element[i].out.format != EMIT_1F_PSIZE)
{
+ emit.element[i].type = TRANSLATE_ELEMENT_NORMAL;
emit.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
emit.element[i].input_buffer = 0;
emit.element[i].input_offset = key->element[i].out.vs_output * 4 * sizeof(float);
+ emit.element[i].instance_divisor = 0;
emit.element[i].output_format = draw_translate_vinfo_format(key->element[i].out.format);
emit.element[i].output_offset = key->element[i].out.offset;
assert(emit.element[i].input_offset <= fetch.output_stride);
}
else {
+ emit.element[i].type = TRANSLATE_ELEMENT_NORMAL;
emit.element[i].input_format = PIPE_FORMAT_R32_FLOAT;
emit.element[i].input_buffer = 1;
emit.element[i].input_offset = 0;
+ emit.element[i].instance_divisor = 0;
emit.element[i].output_format = PIPE_FORMAT_R32_FLOAT;
emit.element[i].output_offset = key->element[i].out.offset;
}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c
index ba6f7b15f9e..a4b78f14943 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c
+++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c
@@ -80,27 +80,11 @@ struct fenced_buffer_list
*/
struct fenced_buffer
{
- /*
- * Immutable members.
- */
-
struct pb_buffer base;
+
struct pb_buffer *buffer;
- struct fenced_buffer_list *list;
-
- /**
- * Protected by fenced_buffer_list::mutex
- */
- struct list_head head;
- /**
- * Following members are mutable and protected by this mutex.
- *
- * You may lock this mutex alone, or lock it with fenced_buffer_list::mutex
- * held, but in order to prevent deadlocks you must never lock
- * fenced_buffer_list::mutex with this mutex held.
- */
- pipe_mutex mutex;
+ /* FIXME: protect access with mutex */
/**
* A bitmask of PIPE_BUFFER_USAGE_CPU/GPU_READ/WRITE describing the current
@@ -112,6 +96,9 @@ struct fenced_buffer
struct pb_validate *vl;
unsigned validation_flags;
struct pipe_fence_handle *fence;
+
+ struct list_head head;
+ struct fenced_buffer_list *list;
};
@@ -123,24 +110,15 @@ fenced_buffer(struct pb_buffer *buf)
}
-/**
- * Add the buffer to the fenced list.
- *
- * fenced_buffer_list::mutex and fenced_buffer::mutex must be held, in this
- * order, before calling this function.
- *
- * Reference count should be incremented before calling this function.
- */
static INLINE void
-fenced_buffer_add_locked(struct fenced_buffer_list *fenced_list,
- struct fenced_buffer *fenced_buf)
+_fenced_buffer_add(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->flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE);
assert(fenced_buf->fence);
- /* TODO: Move the reference count increment here */
-
#ifdef DEBUG
LIST_DEL(&fenced_buf->head);
assert(fenced_list->numUnfenced);
@@ -152,16 +130,32 @@ fenced_buffer_add_locked(struct fenced_buffer_list *fenced_list,
/**
- * Remove the buffer from the fenced list.
- *
- * fenced_buffer_list::mutex and fenced_buffer::mutex must be held, in this
- * order before calling this function.
- *
- * Reference count should be decremented after calling this function.
+ * Actually destroy the buffer.
*/
static INLINE void
-fenced_buffer_remove_locked(struct fenced_buffer_list *fenced_list,
- struct fenced_buffer *fenced_buf)
+_fenced_buffer_destroy(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);
+ FREE(fenced_buf);
+}
+
+
+static INLINE void
+_fenced_buffer_remove(struct fenced_buffer_list *fenced_list,
+ struct fenced_buffer *fenced_buf)
{
struct pb_fence_ops *ops = fenced_list->ops;
@@ -183,56 +177,37 @@ fenced_buffer_remove_locked(struct fenced_buffer_list *fenced_list,
++fenced_list->numUnfenced;
#endif
- /* TODO: Move the reference count decrement and destruction here */
+ /**
+ * FIXME!!!
+ */
+
+ if(!pipe_is_referenced(&fenced_buf->base.base.reference))
+ _fenced_buffer_destroy(fenced_buf);
}
-/**
- * Wait for the fence to expire, and remove it from the fenced list.
- *
- * fenced_buffer::mutex must be held. fenced_buffer_list::mutex must not be
- * held -- it will be acquired internally.
- */
static INLINE enum pipe_error
-fenced_buffer_finish_locked(struct fenced_buffer_list *fenced_list,
- struct fenced_buffer *fenced_buf)
+_fenced_buffer_finish(struct fenced_buffer *fenced_buf)
{
+ struct fenced_buffer_list *fenced_list = fenced_buf->list;
struct pb_fence_ops *ops = fenced_list->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);
-
- /*
- * Acquire the global lock. Must release buffer mutex first to preserve
- * lock order.
- */
- pipe_mutex_unlock(fenced_buf->mutex);
- pipe_mutex_lock(fenced_list->mutex);
- pipe_mutex_lock(fenced_buf->mutex);
-
if(fenced_buf->fence) {
- if(ops->fence_finish(ops, fenced_buf->fence, 0) == 0) {
- /* Remove from the fenced list */
- /* TODO: remove consequents */
- fenced_buffer_remove_locked(fenced_list, fenced_buf);
-
- p_atomic_dec(&fenced_buf->base.base.reference.count);
- assert(pipe_is_referenced(&fenced_buf->base.base.reference));
-
- fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE;
-
- ret = PIPE_OK;
+ if(ops->fence_finish(ops, fenced_buf->fence, 0) != 0) {
+ return PIPE_ERROR;
}
+ /* Remove from the fenced list */
+ /* TODO: remove consequents */
+ _fenced_buffer_remove(fenced_list, fenced_buf);
}
- pipe_mutex_unlock(fenced_list->mutex);
-
- return ret;
+ fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE;
+ return PIPE_OK;
}
@@ -240,8 +215,8 @@ fenced_buffer_finish_locked(struct fenced_buffer_list *fenced_list,
* Free as many fenced buffers from the list head as possible.
*/
static void
-fenced_buffer_list_check_free_locked(struct fenced_buffer_list *fenced_list,
- int wait)
+_fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list,
+ int wait)
{
struct pb_fence_ops *ops = fenced_list->ops;
struct list_head *curr, *next;
@@ -254,29 +229,21 @@ fenced_buffer_list_check_free_locked(struct fenced_buffer_list *fenced_list,
while(curr != &fenced_list->delayed) {
fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head);
- pipe_mutex_lock(fenced_buf->mutex);
-
if(fenced_buf->fence != prev_fence) {
int signaled;
if (wait)
signaled = ops->fence_finish(ops, fenced_buf->fence, 0);
else
signaled = ops->fence_signalled(ops, fenced_buf->fence, 0);
- if (signaled != 0) {
- pipe_mutex_unlock(fenced_buf->mutex);
+ if (signaled != 0)
break;
- }
prev_fence = fenced_buf->fence;
}
else {
assert(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0);
}
- fenced_buffer_remove_locked(fenced_list, fenced_buf);
- pipe_mutex_unlock(fenced_buf->mutex);
-
- pb_buf = &fenced_buf->base;
- pb_reference(&pb_buf, NULL);
+ _fenced_buffer_remove(fenced_list, fenced_buf);
curr = next;
next = curr->next;
@@ -290,25 +257,30 @@ fenced_buffer_destroy(struct pb_buffer *buf)
struct fenced_buffer *fenced_buf = fenced_buffer(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
pipe_mutex_lock(fenced_list->mutex);
- assert(fenced_buf->head.prev);
- assert(fenced_buf->head.next);
- LIST_DEL(&fenced_buf->head);
- assert(fenced_list->numUnfenced);
- --fenced_list->numUnfenced;
+ 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 */
+ }
+ }
+ else {
+ _fenced_buffer_destroy(fenced_buf);
+ }
pipe_mutex_unlock(fenced_list->mutex);
-#else
- (void)fenced_list;
-#endif
-
- pb_reference(&fenced_buf->buffer, NULL);
-
- pipe_mutex_destroy(fenced_buf->mutex);
- FREE(fenced_buf);
}
@@ -319,23 +291,24 @@ fenced_buffer_map(struct pb_buffer *buf,
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 = NULL;
-
- pipe_mutex_lock(fenced_buf->mutex);
+ void *map;
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) &&
- ops->fence_signalled(ops, fenced_buf->fence, 0) == 0) {
+ if(flags & PIPE_BUFFER_USAGE_DONTBLOCK) {
/* Don't wait for the GPU to finish writing */
- goto done;
+ if(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0)
+ _fenced_buffer_remove(fenced_list, fenced_buf);
+ else
+ return NULL;
+ }
+ else {
+ /* Wait for the GPU to finish writing */
+ _fenced_buffer_finish(fenced_buf);
}
-
- /* Wait for the GPU to finish writing */
- fenced_buffer_finish_locked(fenced_list, fenced_buf);
}
#if 0
@@ -352,9 +325,6 @@ fenced_buffer_map(struct pb_buffer *buf,
fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE;
}
-done:
- pipe_mutex_unlock(fenced_buf->mutex);
-
return map;
}
@@ -363,9 +333,6 @@ static void
fenced_buffer_unmap(struct pb_buffer *buf)
{
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
-
- pipe_mutex_lock(fenced_buf->mutex);
-
assert(fenced_buf->mapcount);
if(fenced_buf->mapcount) {
pb_unmap(fenced_buf->buffer);
@@ -373,8 +340,6 @@ fenced_buffer_unmap(struct pb_buffer *buf)
if(!fenced_buf->mapcount)
fenced_buf->flags &= ~PIPE_BUFFER_USAGE_CPU_READ_WRITE;
}
-
- pipe_mutex_unlock(fenced_buf->mutex);
}
@@ -386,14 +351,11 @@ fenced_buffer_validate(struct pb_buffer *buf,
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
enum pipe_error ret;
- pipe_mutex_lock(fenced_buf->mutex);
-
if(!vl) {
/* invalidate */
fenced_buf->vl = NULL;
fenced_buf->validation_flags = 0;
- ret = PIPE_OK;
- goto done;
+ return PIPE_OK;
}
assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE);
@@ -401,17 +363,14 @@ fenced_buffer_validate(struct pb_buffer *buf,
flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE;
/* Buffer cannot be validated in two different lists */
- if(fenced_buf->vl && fenced_buf->vl != vl) {
- ret = PIPE_ERROR_RETRY;
- goto done;
- }
+ 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 */
- ret = PIPE_ERROR_RETRY;
- goto done;
+ return PIPE_ERROR_RETRY;
}
/* Final sanity checking */
assert(!(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE));
@@ -421,21 +380,17 @@ fenced_buffer_validate(struct pb_buffer *buf,
if(fenced_buf->vl == vl &&
(fenced_buf->validation_flags & flags) == flags) {
/* Nothing to do -- buffer already validated */
- ret = PIPE_OK;
- goto done;
+ return PIPE_OK;
}
ret = pb_validate(fenced_buf->buffer, vl, flags);
if (ret != PIPE_OK)
- goto done;
+ return ret;
fenced_buf->vl = vl;
fenced_buf->validation_flags |= flags;
-done:
- pipe_mutex_unlock(fenced_buf->mutex);
-
- return ret;
+ return PIPE_OK;
}
@@ -450,36 +405,29 @@ fenced_buffer_fence(struct pb_buffer *buf,
fenced_buf = fenced_buffer(buf);
fenced_list = fenced_buf->list;
ops = fenced_list->ops;
-
- pipe_mutex_lock(fenced_list->mutex);
- pipe_mutex_lock(fenced_buf->mutex);
-
- assert(pipe_is_referenced(&fenced_buf->base.base.reference));
-
- if(fence != fenced_buf->fence) {
- assert(fenced_buf->vl);
- assert(fenced_buf->validation_flags);
-
- if (fenced_buf->fence) {
- fenced_buffer_remove_locked(fenced_list, fenced_buf);
- p_atomic_dec(&fenced_buf->base.base.reference.count);
- assert(pipe_is_referenced(&fenced_buf->base.base.reference));
- }
- if (fence) {
- ops->fence_reference(ops, &fenced_buf->fence, fence);
- fenced_buf->flags |= fenced_buf->validation_flags;
- p_atomic_inc(&fenced_buf->base.base.reference.count);
- fenced_buffer_add_locked(fenced_list, fenced_buf);
- }
-
- pb_fence(fenced_buf->buffer, fence);
- fenced_buf->vl = NULL;
- fenced_buf->validation_flags = 0;
+ if(fence == fenced_buf->fence) {
+ /* Nothing to do */
+ return;
}
- pipe_mutex_unlock(fenced_buf->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);
+ }
pipe_mutex_unlock(fenced_list->mutex);
+
+ pb_fence(fenced_buf->buffer, fence);
+
+ fenced_buf->vl = NULL;
+ fenced_buf->validation_flags = 0;
}
@@ -489,7 +437,6 @@ fenced_buffer_get_base_buffer(struct pb_buffer *buf,
pb_size *offset)
{
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
- /* NOTE: accesses immutable members only -- mutex not necessary */
pb_get_base_buffer(fenced_buf->buffer, base_buf, offset);
}
@@ -529,8 +476,6 @@ fenced_buffer_create(struct fenced_buffer_list *fenced_list,
buf->buffer = buffer;
buf->list = fenced_list;
- pipe_mutex_init(buf->mutex);
-
#ifdef DEBUG
pipe_mutex_lock(fenced_list->mutex);
LIST_ADDTAIL(&buf->head, &fenced_list->unfenced);
@@ -572,7 +517,7 @@ fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list,
int wait)
{
pipe_mutex_lock(fenced_list->mutex);
- fenced_buffer_list_check_free_locked(fenced_list, wait);
+ _fenced_buffer_list_check_free(fenced_list, wait);
pipe_mutex_unlock(fenced_list->mutex);
}
@@ -594,13 +539,11 @@ fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list)
next = curr->next;
while(curr != &fenced_list->unfenced) {
fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head);
- pipe_mutex_lock(fenced_buf->mutex);
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));
- pipe_mutex_unlock(fenced_buf->mutex);
curr = next;
next = curr->next;
}
@@ -610,7 +553,6 @@ fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list)
while(curr != &fenced_list->delayed) {
int signaled;
fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head);
- pipe_mutex_lock(fenced_buf->mutex);
signaled = ops->fence_signalled(ops, fenced_buf->fence, 0);
debug_printf("%10p %7u %7u %10p %s\n",
(void *) fenced_buf,
@@ -618,7 +560,6 @@ fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list)
p_atomic_read(&fenced_buf->base.base.reference.count),
(void *) fenced_buf->fence,
signaled == 0 ? "y" : "n");
- pipe_mutex_unlock(fenced_buf->mutex);
curr = next;
next = curr->next;
}
@@ -639,8 +580,8 @@ fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list)
#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);
- fenced_buffer_list_check_free_locked(fenced_list, 1);
}
#ifdef DEBUG
@@ -648,7 +589,6 @@ fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list)
#endif
pipe_mutex_unlock(fenced_list->mutex);
- pipe_mutex_destroy(fenced_list->mutex);
fenced_list->ops->destroy(fenced_list->ops);
diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
index 1acf3c373eb..f675427d987 100644
--- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
+++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
@@ -673,6 +673,13 @@ void x86_and( struct x86_function *p,
emit_op_modrm( p, 0x23, 0x21, dst, src );
}
+void x86_div( struct x86_function *p,
+ struct x86_reg src )
+{
+ assert(src.file == file_REG32 && src.mod == mod_REG);
+ emit_op_modrm(p, 0xf7, 0, x86_make_reg(file_REG32, 6), src);
+}
+
/***********************************************************************
diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h
index 731a6517968..f7612d416a0 100644
--- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h
+++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h
@@ -244,6 +244,7 @@ void x86_sub( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
void x86_test( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
void x86_xor( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
void x86_sahf( struct x86_function *p );
+void x86_div( struct x86_function *p, struct x86_reg src );
void x86_cdecl_caller_push_regs( struct x86_function *p );
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c
index e2e5394f86f..d7ff262f30a 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_dump.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c
@@ -123,7 +123,8 @@ static const char *semantic_names[] =
"NORMAL",
"FACE",
"EDGEFLAG",
- "PRIM_ID"
+ "PRIM_ID",
+ "INSTANCEID"
};
static const char *immediate_type_names[] =
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 2bcb33392a8..118a638ab48 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -1041,11 +1041,19 @@ fetch_src_file_channel(
default:
assert( 0 );
+ chan->u[0] = 0;
+ chan->u[1] = 0;
+ chan->u[2] = 0;
+ chan->u[3] = 0;
}
break;
default:
assert( 0 );
+ chan->u[0] = 0;
+ chan->u[1] = 0;
+ chan->u[2] = 0;
+ chan->u[3] = 0;
}
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ppc.c b/src/gallium/auxiliary/tgsi/tgsi_ppc.c
index 138d2d095bb..ad553c71a57 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ppc.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ppc.c
@@ -51,7 +51,8 @@
* Since it's pretty much impossible to form PPC vector immediates, load
* them from memory here:
*/
-const float ppc_builtin_constants[] ALIGN16_ATTRIB = {
+PIPE_ALIGN_VAR(16) const float
+ppc_builtin_constants[] = {
1.0f, -128.0f, 128.0, 0.0
};
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
index 7f1c8e5dd68..e1e4f97967d 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
@@ -335,13 +335,13 @@ iter_instruction(
fill_scan_register1d(ind_reg,
inst->Src[i].Indirect.File,
inst->Src[i].Indirect.Index);
- if (!(reg->file == TGSI_FILE_ADDRESS || reg->file == TGSI_FILE_LOOP) ||
- reg->indices[0] != 0) {
+ 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,
- reg,
+ ind_reg,
"indirect",
FALSE );
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c
index 2e13a7aaf9d..a85cc4659e0 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c
@@ -2146,40 +2146,50 @@ emit_instruction(
break;
case TGSI_OPCODE_XPD:
+ /* Note: we do all stores after all operands have been fetched
+ * to avoid src/dst register aliasing issues for an instruction
+ * such as: XPD TEMP[2].xyz, TEMP[0], TEMP[2];
+ */
if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ) {
- FETCH( func, *inst, 1, 1, CHAN_Z );
- FETCH( func, *inst, 3, 0, CHAN_Z );
+ FETCH( func, *inst, 1, 1, CHAN_Z ); /* xmm[1] = src[1].z */
+ FETCH( func, *inst, 3, 0, CHAN_Z ); /* xmm[3] = src[0].z */
}
if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
- FETCH( func, *inst, 0, 0, CHAN_Y );
- FETCH( func, *inst, 4, 1, CHAN_Y );
+ FETCH( func, *inst, 0, 0, CHAN_Y ); /* xmm[0] = src[0].y */
+ FETCH( func, *inst, 4, 1, CHAN_Y ); /* xmm[4] = src[1].y */
}
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) {
- emit_MOV( func, 2, 0 );
- emit_mul( func, 2, 1 );
- emit_MOV( func, 5, 3 );
- emit_mul( func, 5, 4 );
- emit_sub( func, 2, 5 );
- STORE( func, *inst, 2, 0, CHAN_X );
+ emit_MOV( func, 7, 0 ); /* xmm[7] = xmm[0] */
+ emit_mul( func, 7, 1 ); /* xmm[7] = xmm[2] * xmm[1] */
+ emit_MOV( func, 5, 3 ); /* xmm[5] = xmm[3] */
+ emit_mul( func, 5, 4 ); /* xmm[5] = xmm[5] * xmm[4] */
+ emit_sub( func, 7, 5 ); /* xmm[7] = xmm[2] - xmm[5] */
+ /* store xmm[7] in dst.x below */
}
if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ||
IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
- FETCH( func, *inst, 2, 1, CHAN_X );
- FETCH( func, *inst, 5, 0, CHAN_X );
+ FETCH( func, *inst, 2, 1, CHAN_X ); /* xmm[2] = src[1].x */
+ FETCH( func, *inst, 5, 0, CHAN_X ); /* xmm[5] = src[0].x */
}
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) {
- emit_mul( func, 3, 2 );
- emit_mul( func, 1, 5 );
- emit_sub( func, 3, 1 );
- STORE( func, *inst, 3, 0, CHAN_Y );
+ emit_mul( func, 3, 2 ); /* xmm[3] = xmm[3] * xmm[2] */
+ emit_mul( func, 1, 5 ); /* xmm[1] = xmm[1] * xmm[5] */
+ emit_sub( func, 3, 1 ); /* xmm[3] = xmm[3] - xmm[1] */
+ /* store xmm[3] in dst.y below */
}
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) {
- emit_mul( func, 5, 4 );
- emit_mul( func, 0, 2 );
- emit_sub( func, 5, 0 );
- STORE( func, *inst, 5, 0, CHAN_Z );
+ emit_mul( func, 5, 4 ); /* xmm[5] = xmm[5] * xmm[4] */
+ emit_mul( func, 0, 2 ); /* xmm[0] = xmm[0] * xmm[2] */
+ emit_sub( func, 5, 0 ); /* xmm[5] = xmm[5] - xmm[0] */
+ STORE( func, *inst, 5, 0, CHAN_Z ); /* dst.z = xmm[5] */
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) {
+ STORE( func, *inst, 7, 0, CHAN_X ); /* dst.x = xmm[7] */
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) {
+ STORE( func, *inst, 3, 0, CHAN_Y ); /* dst.y = xmm[3] */
}
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W ) {
emit_tempf(
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
index e64e2b731df..8bd6f68dcc0 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -40,6 +40,8 @@ union tgsi_any_token {
struct tgsi_header header;
struct tgsi_processor processor;
struct tgsi_token token;
+ struct tgsi_property prop;
+ struct tgsi_property_data prop_data;
struct tgsi_declaration decl;
struct tgsi_declaration_range decl_range;
struct tgsi_declaration_semantic decl_semantic;
@@ -64,6 +66,7 @@ struct ureg_tokens {
};
#define UREG_MAX_INPUT PIPE_MAX_ATTRIBS
+#define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS
#define UREG_MAX_OUTPUT PIPE_MAX_ATTRIBS
#define UREG_MAX_CONSTANT_RANGE 32
#define UREG_MAX_IMMEDIATE 32
@@ -95,6 +98,13 @@ struct ureg_program
unsigned nr_gs_inputs;
struct {
+ unsigned index;
+ unsigned semantic_name;
+ unsigned semantic_index;
+ } system_value[UREG_MAX_SYSTEM_VALUE];
+ unsigned nr_system_values;
+
+ struct {
unsigned semantic_name;
unsigned semantic_index;
} output[UREG_MAX_OUTPUT];
@@ -123,6 +133,8 @@ struct ureg_program
} constant_range[UREG_MAX_CONSTANT_RANGE];
unsigned nr_constant_ranges;
+ unsigned property_gs_input_prim;
+
unsigned nr_addrs;
unsigned nr_preds;
unsigned nr_loops;
@@ -234,19 +246,28 @@ ureg_src_register( unsigned file,
src.SwizzleY = TGSI_SWIZZLE_Y;
src.SwizzleZ = TGSI_SWIZZLE_Z;
src.SwizzleW = TGSI_SWIZZLE_W;
- src.Pad = 0;
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;
}
+void
+ureg_property_gs_input_prim(struct ureg_program *ureg,
+ unsigned gs_input_prim)
+{
+ ureg->property_gs_input_prim = gs_input_prim;
+}
+
+
struct ureg_src
ureg_DECL_fs_input( struct ureg_program *ureg,
@@ -304,6 +325,25 @@ ureg_DECL_gs_input(struct ureg_program *ureg,
}
+struct ureg_src
+ureg_DECL_system_value(struct ureg_program *ureg,
+ unsigned index,
+ unsigned semantic_name,
+ unsigned semantic_index)
+{
+ if (ureg->nr_system_values < UREG_MAX_SYSTEM_VALUE) {
+ ureg->system_value[ureg->nr_system_values].index = index;
+ ureg->system_value[ureg->nr_system_values].semantic_name = semantic_name;
+ ureg->system_value[ureg->nr_system_values].semantic_index = semantic_index;
+ ureg->nr_system_values++;
+ } else {
+ set_bad(ureg);
+ }
+
+ return ureg_src_register(TGSI_FILE_SYSTEM_VALUE, index);
+}
+
+
struct ureg_dst
ureg_DECL_output( struct ureg_program *ureg,
unsigned name,
@@ -628,7 +668,7 @@ void
ureg_emit_src( struct ureg_program *ureg,
struct ureg_src src )
{
- unsigned size = 1 + (src.Indirect ? 1 : 0);
+ unsigned size = 1 + (src.Indirect ? 1 : 0) + (src.Dimension ? 1 : 0);
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
unsigned n = 0;
@@ -660,6 +700,15 @@ ureg_emit_src( struct ureg_program *ureg,
n++;
}
+ if (src.Dimension) {
+ out[0].src.Dimension = 1;
+ out[n].dim.Indirect = 0;
+ out[n].dim.Dimension = 0;
+ out[n].dim.Padding = 0;
+ out[n].dim.Index = src.DimensionIndex;
+ n++;
+ }
+
assert(n == size);
}
@@ -1027,13 +1076,34 @@ emit_immediate( struct ureg_program *ureg,
out[4].imm_data.Uint = v[3];
}
+static void
+emit_property(struct ureg_program *ureg,
+ unsigned name,
+ unsigned data)
+{
+ union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2);
+ out[0].value = 0;
+ out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY;
+ out[0].prop.NrTokens = 2;
+ out[0].prop.PropertyName = name;
+
+ out[1].prop_data.Data = data;
+}
static void emit_decls( struct ureg_program *ureg )
{
unsigned i;
+ if (ureg->property_gs_input_prim != ~0) {
+ assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
+
+ emit_property(ureg,
+ TGSI_PROPERTY_GS_INPUT_PRIM,
+ ureg->property_gs_input_prim);
+ }
+
if (ureg->processor == TGSI_PROCESSOR_VERTEX) {
for (i = 0; i < UREG_MAX_INPUT; i++) {
if (ureg->vs_inputs[i/32] & (1 << (i%32))) {
@@ -1058,6 +1128,15 @@ static void emit_decls( struct ureg_program *ureg )
}
}
+ for (i = 0; i < ureg->nr_system_values; i++) {
+ emit_decl(ureg,
+ TGSI_FILE_SYSTEM_VALUE,
+ ureg->system_value[i].index,
+ ureg->system_value[i].semantic_name,
+ ureg->system_value[i].semantic_index,
+ TGSI_INTERPOLATE_CONSTANT);
+ }
+
for (i = 0; i < ureg->nr_outputs; i++) {
emit_decl( ureg,
TGSI_FILE_OUTPUT,
@@ -1234,6 +1313,7 @@ struct ureg_program *ureg_create( unsigned processor )
return NULL;
ureg->processor = processor;
+ ureg->property_gs_input_prim = ~0;
return ureg;
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
index 6f11273320a..03eaf24854c 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
@@ -47,13 +47,14 @@ struct ureg_src
unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
- unsigned Pad : 1; /* BOOL */
unsigned Indirect : 1; /* BOOL */
+ unsigned Dimension : 1; /* BOOL */
unsigned Absolute : 1; /* BOOL */
- int Index : 16; /* SINT */
unsigned Negate : 1; /* BOOL */
+ int Index : 16; /* SINT */
int IndirectIndex : 16; /* SINT */
int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
+ int DimensionIndex : 16; /* SINT */
};
/* Very similar to a tgsi_dst_register, removing unsupported fields
@@ -118,6 +119,14 @@ ureg_create_shader_and_destroy( struct ureg_program *p,
}
+/***********************************************************************
+ * Build shader properties:
+ */
+
+void
+ureg_property_gs_input_prim(struct ureg_program *ureg,
+ unsigned gs_input_prim);
+
/***********************************************************************
* Build shader declarations:
@@ -137,6 +146,12 @@ struct ureg_src
ureg_DECL_gs_input(struct ureg_program *,
unsigned index);
+struct ureg_src
+ureg_DECL_system_value(struct ureg_program *,
+ unsigned index,
+ unsigned semantic_name,
+ unsigned semantic_index);
+
struct ureg_dst
ureg_DECL_output( struct ureg_program *,
unsigned semantic_name,
@@ -760,6 +775,15 @@ ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
return reg;
}
+static INLINE struct ureg_src
+ureg_src_dimension( struct ureg_src reg, int index )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ reg.Dimension = 1;
+ reg.DimensionIndex = index;
+ return reg;
+}
+
static INLINE struct ureg_dst
ureg_dst( struct ureg_src src )
{
@@ -792,13 +816,14 @@ ureg_src( struct ureg_dst dst )
src.SwizzleY = TGSI_SWIZZLE_Y;
src.SwizzleZ = TGSI_SWIZZLE_Z;
src.SwizzleW = TGSI_SWIZZLE_W;
- src.Pad = 0;
src.Indirect = dst.Indirect;
src.IndirectIndex = dst.IndirectIndex;
src.IndirectSwizzle = dst.IndirectSwizzle;
src.Absolute = 0;
src.Index = dst.Index;
src.Negate = 0;
+ src.Dimension = 0;
+ src.DimensionIndex = 0;
return src;
}
@@ -837,13 +862,14 @@ ureg_src_undef( void )
src.SwizzleY = 0;
src.SwizzleZ = 0;
src.SwizzleW = 0;
- src.Pad = 0;
src.Indirect = 0;
src.IndirectIndex = 0;
src.IndirectSwizzle = 0;
src.Absolute = 0;
src.Index = 0;
src.Negate = 0;
+ src.Dimension = 0;
+ src.DimensionIndex = 0;
return src;
}
diff --git a/src/gallium/auxiliary/translate/translate.h b/src/gallium/auxiliary/translate/translate.h
index 34526eb0617..54ed2c1a4be 100644
--- a/src/gallium/auxiliary/translate/translate.h
+++ b/src/gallium/auxiliary/translate/translate.h
@@ -44,12 +44,19 @@
#include "pipe/p_format.h"
#include "pipe/p_state.h"
+enum translate_element_type {
+ TRANSLATE_ELEMENT_NORMAL,
+ TRANSLATE_ELEMENT_INSTANCE_ID
+};
+
struct translate_element
{
+ enum translate_element_type type;
enum pipe_format input_format;
enum pipe_format output_format;
unsigned input_buffer:8;
unsigned input_offset:24;
+ unsigned instance_divisor;
unsigned output_offset;
};
@@ -74,11 +81,13 @@ struct translate {
void (PIPE_CDECL *run_elts)( struct translate *,
const unsigned *elts,
unsigned count,
+ unsigned instance_id,
void *output_buffer);
void (PIPE_CDECL *run)( struct translate *,
unsigned start,
unsigned count,
+ unsigned instance_id,
void *output_buffer);
};
@@ -103,8 +112,13 @@ static INLINE int translate_keysize( const struct translate_key *key )
static INLINE int translate_key_compare( const struct translate_key *a,
const struct translate_key *b )
{
- int keysize = translate_keysize(a);
- return memcmp(a, b, keysize);
+ int keysize_a = translate_keysize(a);
+ int keysize_b = translate_keysize(b);
+
+ if (keysize_a != keysize_b) {
+ return keysize_a - keysize_b;
+ }
+ return memcmp(a, b, keysize_a);
}
diff --git a/src/gallium/auxiliary/translate/translate_generic.c b/src/gallium/auxiliary/translate/translate_generic.c
index 266e7ee81e6..24727d49888 100644
--- a/src/gallium/auxiliary/translate/translate_generic.c
+++ b/src/gallium/auxiliary/translate/translate_generic.c
@@ -46,9 +46,12 @@ struct translate_generic {
struct translate translate;
struct {
+ enum translate_element_type type;
+
fetch_func fetch;
unsigned buffer;
unsigned input_offset;
+ unsigned instance_divisor;
emit_func emit;
unsigned output_offset;
@@ -568,6 +571,7 @@ static emit_func get_emit_func( enum pipe_format format )
static void PIPE_CDECL generic_run_elts( struct translate *translate,
const unsigned *elts,
unsigned count,
+ unsigned instance_id,
void *output_buffer )
{
struct translate_generic *tg = translate_generic(translate);
@@ -583,13 +587,20 @@ static void PIPE_CDECL generic_run_elts( struct translate *translate,
for (attr = 0; attr < nr_attrs; attr++) {
float data[4];
-
- const char *src = (tg->attrib[attr].input_ptr +
- tg->attrib[attr].input_stride * elt);
+ const char *src;
char *dst = (vert +
tg->attrib[attr].output_offset);
+ if (tg->attrib[attr].instance_divisor) {
+ src = tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride *
+ (instance_id / tg->attrib[attr].instance_divisor);
+ } else {
+ src = tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride * elt;
+ }
+
tg->attrib[attr].fetch( src, data );
if (0) debug_printf("vert %d/%d attr %d: %f %f %f %f\n",
@@ -607,6 +618,7 @@ static void PIPE_CDECL generic_run_elts( struct translate *translate,
static void PIPE_CDECL generic_run( struct translate *translate,
unsigned start,
unsigned count,
+ unsigned instance_id,
void *output_buffer )
{
struct translate_generic *tg = translate_generic(translate);
@@ -623,13 +635,25 @@ static void PIPE_CDECL generic_run( struct translate *translate,
for (attr = 0; attr < nr_attrs; attr++) {
float data[4];
- const char *src = (tg->attrib[attr].input_ptr +
- tg->attrib[attr].input_stride * elt);
-
char *dst = (vert +
tg->attrib[attr].output_offset);
- tg->attrib[attr].fetch( src, data );
+ if (tg->attrib[attr].type == TRANSLATE_ELEMENT_NORMAL) {
+ const char *src;
+
+ if (tg->attrib[attr].instance_divisor) {
+ src = tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride *
+ (instance_id / tg->attrib[attr].instance_divisor);
+ } else {
+ src = tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride * elt;
+ }
+
+ tg->attrib[attr].fetch( src, data );
+ } else {
+ data[0] = (float)instance_id;
+ }
if (0) debug_printf("vert %d attr %d: %f %f %f %f\n",
i, attr, data[0], data[1], data[2], data[3]);
@@ -683,10 +707,12 @@ struct translate *translate_generic_create( const struct translate_key *key )
tg->translate.run = generic_run;
for (i = 0; i < key->nr_elements; i++) {
+ tg->attrib[i].type = key->element[i].type;
tg->attrib[i].fetch = get_fetch_func(key->element[i].input_format);
tg->attrib[i].buffer = key->element[i].input_buffer;
tg->attrib[i].input_offset = key->element[i].input_offset;
+ tg->attrib[i].instance_divisor = key->element[i].instance_divisor;
tg->attrib[i].emit = get_emit_func(key->element[i].output_format);
tg->attrib[i].output_offset = key->element[i].output_offset;
diff --git a/src/gallium/auxiliary/translate/translate_sse.c b/src/gallium/auxiliary/translate/translate_sse.c
index b62db8d8f33..c13e7427387 100644
--- a/src/gallium/auxiliary/translate/translate_sse.c
+++ b/src/gallium/auxiliary/translate/translate_sse.c
@@ -49,19 +49,29 @@
typedef void (PIPE_CDECL *run_func)( struct translate *translate,
unsigned start,
unsigned count,
- void *output_buffer );
+ unsigned instance_id,
+ void *output_buffer);
typedef void (PIPE_CDECL *run_elts_func)( struct translate *translate,
const unsigned *elts,
unsigned count,
- void *output_buffer );
+ unsigned instance_id,
+ void *output_buffer);
struct translate_buffer {
const void *base_ptr;
unsigned stride;
- void *ptr; /* updated per vertex */
};
+struct translate_buffer_varient {
+ unsigned buffer_index;
+ unsigned instance_divisor;
+ void *ptr; /* updated either per vertex or per instance */
+};
+
+
+#define ELEMENT_BUFFER_INSTANCE_ID 1001
+
struct translate_sse {
struct translate translate;
@@ -81,6 +91,16 @@ struct translate_sse {
struct translate_buffer buffer[PIPE_MAX_ATTRIBS];
unsigned nr_buffers;
+ /* Multiple buffer varients can map to a single buffer. */
+ struct translate_buffer_varient buffer_varient[PIPE_MAX_ATTRIBS];
+ unsigned nr_buffer_varients;
+
+ /* Multiple elements can map to a single buffer varient. */
+ unsigned element_to_buffer_varient[PIPE_MAX_ATTRIBS];
+
+ boolean use_instancing;
+ unsigned instance_id;
+
run_func gen_run;
run_elts_func gen_run_elts;
@@ -359,32 +379,61 @@ static boolean init_inputs( struct translate_sse *p,
boolean linear )
{
unsigned i;
- if (linear) {
- for (i = 0; i < p->nr_buffers; i++) {
+ struct x86_reg instance_id = x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->instance_id));
+
+ for (i = 0; i < p->nr_buffer_varients; i++) {
+ struct translate_buffer_varient *varient = &p->buffer_varient[i];
+ struct translate_buffer *buffer = &p->buffer[varient->buffer_index];
+
+ if (linear || varient->instance_divisor) {
struct x86_reg buf_stride = x86_make_disp(p->machine_EDX,
- get_offset(p, &p->buffer[i].stride));
+ get_offset(p, &buffer->stride));
struct x86_reg buf_ptr = x86_make_disp(p->machine_EDX,
- get_offset(p, &p->buffer[i].ptr));
+ get_offset(p, &varient->ptr));
struct x86_reg buf_base_ptr = x86_make_disp(p->machine_EDX,
- get_offset(p, &p->buffer[i].base_ptr));
+ get_offset(p, &buffer->base_ptr));
struct x86_reg elt = p->idx_EBX;
- struct x86_reg tmp = p->tmp_EAX;
-
+ struct x86_reg tmp_EAX = p->tmp_EAX;
/* Calculate pointer to first attrib:
+ * base_ptr + stride * index, where index depends on instance divisor
*/
- x86_mov(p->func, tmp, buf_stride);
- x86_imul(p->func, tmp, elt);
- x86_add(p->func, tmp, buf_base_ptr);
+ if (varient->instance_divisor) {
+ /* Our index is instance ID divided by instance divisor.
+ */
+ x86_mov(p->func, tmp_EAX, instance_id);
+
+ if (varient->instance_divisor != 1) {
+ struct x86_reg tmp_EDX = p->machine_EDX;
+ struct x86_reg tmp_ECX = p->outbuf_ECX;
+
+ /* TODO: Add x86_shr() to rtasm and use it whenever
+ * instance divisor is power of two.
+ */
+
+ x86_push(p->func, tmp_EDX);
+ x86_push(p->func, tmp_ECX);
+ x86_xor(p->func, tmp_EDX, tmp_EDX);
+ x86_mov_reg_imm(p->func, tmp_ECX, varient->instance_divisor);
+ x86_div(p->func, tmp_ECX); /* EAX = EDX:EAX / ECX */
+ x86_pop(p->func, tmp_ECX);
+ x86_pop(p->func, tmp_EDX);
+ }
+ } else {
+ x86_mov(p->func, tmp_EAX, elt);
+ }
+ x86_imul(p->func, tmp_EAX, buf_stride);
+ x86_add(p->func, tmp_EAX, buf_base_ptr);
/* In the linear case, keep the buffer pointer instead of the
* index number.
*/
- if (p->nr_buffers == 1)
- x86_mov( p->func, elt, tmp );
+ if (linear && p->nr_buffer_varients == 1)
+ x86_mov(p->func, elt, tmp_EAX);
else
- x86_mov( p->func, buf_ptr, tmp );
+ x86_mov(p->func, buf_ptr, tmp_EAX);
}
}
@@ -394,31 +443,36 @@ static boolean init_inputs( struct translate_sse *p,
static struct x86_reg get_buffer_ptr( struct translate_sse *p,
boolean linear,
- unsigned buf_idx,
+ unsigned var_idx,
struct x86_reg elt )
{
- if (linear && p->nr_buffers == 1) {
+ if (var_idx == ELEMENT_BUFFER_INSTANCE_ID) {
+ return x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->instance_id));
+ }
+ if (linear && p->nr_buffer_varients == 1) {
return p->idx_EBX;
}
- else if (linear) {
+ else if (linear || p->buffer_varient[var_idx].instance_divisor) {
struct x86_reg ptr = p->tmp_EAX;
struct x86_reg buf_ptr =
x86_make_disp(p->machine_EDX,
- get_offset(p, &p->buffer[buf_idx].ptr));
+ get_offset(p, &p->buffer_varient[var_idx].ptr));
x86_mov(p->func, ptr, buf_ptr);
return ptr;
}
else {
struct x86_reg ptr = p->tmp_EAX;
+ const struct translate_buffer_varient *varient = &p->buffer_varient[var_idx];
struct x86_reg buf_stride =
x86_make_disp(p->machine_EDX,
- get_offset(p, &p->buffer[buf_idx].stride));
+ get_offset(p, &p->buffer[varient->buffer_index].stride));
struct x86_reg buf_base_ptr =
x86_make_disp(p->machine_EDX,
- get_offset(p, &p->buffer[buf_idx].base_ptr));
+ get_offset(p, &p->buffer[varient->buffer_index].base_ptr));
@@ -436,28 +490,33 @@ static struct x86_reg get_buffer_ptr( struct translate_sse *p,
static boolean incr_inputs( struct translate_sse *p,
boolean linear )
{
- if (linear && p->nr_buffers == 1) {
+ if (linear && p->nr_buffer_varients == 1) {
struct x86_reg stride = x86_make_disp(p->machine_EDX,
get_offset(p, &p->buffer[0].stride));
- x86_add(p->func, p->idx_EBX, stride);
- sse_prefetchnta(p->func, x86_make_disp(p->idx_EBX, 192));
+ if (p->buffer_varient[0].instance_divisor == 0) {
+ x86_add(p->func, p->idx_EBX, stride);
+ sse_prefetchnta(p->func, x86_make_disp(p->idx_EBX, 192));
+ }
}
else if (linear) {
unsigned i;
/* Is this worthwhile??
*/
- for (i = 0; i < p->nr_buffers; i++) {
+ for (i = 0; i < p->nr_buffer_varients; i++) {
+ struct translate_buffer_varient *varient = &p->buffer_varient[i];
struct x86_reg buf_ptr = x86_make_disp(p->machine_EDX,
- get_offset(p, &p->buffer[i].ptr));
+ get_offset(p, &varient->ptr));
struct x86_reg buf_stride = x86_make_disp(p->machine_EDX,
- get_offset(p, &p->buffer[i].stride));
+ get_offset(p, &p->buffer[varient->buffer_index].stride));
- x86_mov(p->func, p->tmp_EAX, buf_ptr);
- x86_add(p->func, p->tmp_EAX, buf_stride);
- if (i == 0) sse_prefetchnta(p->func, x86_make_disp(p->tmp_EAX, 192));
- x86_mov(p->func, buf_ptr, p->tmp_EAX);
+ if (varient->instance_divisor == 0) {
+ x86_mov(p->func, p->tmp_EAX, buf_ptr);
+ x86_add(p->func, p->tmp_EAX, buf_stride);
+ if (i == 0) sse_prefetchnta(p->func, x86_make_disp(p->tmp_EAX, 192));
+ x86_mov(p->func, buf_ptr, p->tmp_EAX);
+ }
}
}
else {
@@ -514,7 +573,18 @@ static boolean build_vertex_emit( struct translate_sse *p,
x86_mov(p->func, p->machine_EDX, x86_fn_arg(p->func, 1));
x86_mov(p->func, p->idx_EBX, x86_fn_arg(p->func, 2));
x86_mov(p->func, p->count_ESI, x86_fn_arg(p->func, 3));
- x86_mov(p->func, p->outbuf_ECX, x86_fn_arg(p->func, 4));
+ x86_mov(p->func, p->outbuf_ECX, x86_fn_arg(p->func, 5));
+
+ /* Load instance ID.
+ */
+ if (p->use_instancing) {
+ x86_mov(p->func,
+ p->tmp_EAX,
+ x86_fn_arg(p->func, 4));
+ x86_mov(p->func,
+ x86_make_disp(p->machine_EDX, get_offset(p, &p->instance_id)),
+ p->tmp_EAX);
+ }
/* Get vertex count, compare to zero
*/
@@ -531,17 +601,18 @@ static boolean build_vertex_emit( struct translate_sse *p,
label = x86_get_label(p->func);
{
struct x86_reg elt = linear ? p->idx_EBX : x86_deref(p->idx_EBX);
- int last_vb = -1;
+ int last_varient = -1;
struct x86_reg vb;
for (j = 0; j < p->translate.key.nr_elements; j++) {
const struct translate_element *a = &p->translate.key.element[j];
+ unsigned varient = p->element_to_buffer_varient[j];
/* Figure out source pointer address:
*/
- if (a->input_buffer != last_vb) {
- last_vb = a->input_buffer;
- vb = get_buffer_ptr(p, linear, a->input_buffer, elt);
+ if (varient != last_varient) {
+ last_varient = varient;
+ vb = get_buffer_ptr(p, linear, varient, elt);
}
if (!translate_attr( p, a,
@@ -624,6 +695,7 @@ static void translate_sse_release( struct translate *translate )
static void PIPE_CDECL translate_sse_run_elts( struct translate *translate,
const unsigned *elts,
unsigned count,
+ unsigned instance_id,
void *output_buffer )
{
struct translate_sse *p = (struct translate_sse *)translate;
@@ -631,12 +703,14 @@ static void PIPE_CDECL translate_sse_run_elts( struct translate *translate,
p->gen_run_elts( translate,
elts,
count,
- output_buffer );
+ instance_id,
+ output_buffer);
}
static void PIPE_CDECL translate_sse_run( struct translate *translate,
unsigned start,
unsigned count,
+ unsigned instance_id,
void *output_buffer )
{
struct translate_sse *p = (struct translate_sse *)translate;
@@ -644,7 +718,8 @@ static void PIPE_CDECL translate_sse_run( struct translate *translate,
p->gen_run( translate,
start,
count,
- output_buffer );
+ instance_id,
+ output_buffer);
}
@@ -666,8 +741,37 @@ struct translate *translate_sse2_create( const struct translate_key *key )
p->translate.run_elts = translate_sse_run_elts;
p->translate.run = translate_sse_run;
- for (i = 0; i < key->nr_elements; i++)
- p->nr_buffers = MAX2( p->nr_buffers, key->element[i].input_buffer + 1 );
+ for (i = 0; i < key->nr_elements; i++) {
+ if (key->element[i].type == TRANSLATE_ELEMENT_NORMAL) {
+ unsigned j;
+
+ p->nr_buffers = MAX2(p->nr_buffers, key->element[i].input_buffer + 1);
+
+ if (key->element[i].instance_divisor) {
+ p->use_instancing = TRUE;
+ }
+
+ /*
+ * Map vertex element to vertex buffer varient.
+ */
+ for (j = 0; j < p->nr_buffer_varients; j++) {
+ if (p->buffer_varient[j].buffer_index == key->element[i].input_buffer &&
+ p->buffer_varient[j].instance_divisor == key->element[i].instance_divisor) {
+ break;
+ }
+ }
+ if (j == p->nr_buffer_varients) {
+ p->buffer_varient[j].buffer_index = key->element[i].input_buffer;
+ p->buffer_varient[j].instance_divisor = key->element[i].instance_divisor;
+ p->nr_buffer_varients++;
+ }
+ p->element_to_buffer_varient[i] = j;
+ } else {
+ assert(key->element[i].type == TRANSLATE_ELEMENT_INSTANCE_ID);
+
+ p->element_to_buffer_varient[i] = ELEMENT_BUFFER_INSTANCE_ID;
+ }
+ }
if (0) debug_printf("nr_buffers: %d\n", p->nr_buffers);
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index cef3b69e46d..249a0375fc5 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -163,6 +163,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
rs_state.cull_mode = PIPE_WINDING_NONE;
rs_state.bypass_vs_clip_and_viewport = 1;
rs_state.gl_rasterization_rules = 1;
+ rs_state.flatshade = 1;
ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);
/* fragment shaders are created on-demand */
@@ -378,9 +379,16 @@ static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx,
float t1 = y1 / (float)surf->height;
float s2 = x2 / (float)surf->width;
float t2 = y2 / (float)surf->height;
- const float st[4][2] = {
- {s1, t1}, {s2, t1}, {s2, t2}, {s1, t2}
- };
+ float st[4][2];
+
+ st[0][0] = s1;
+ st[0][1] = t1;
+ st[1][0] = s2;
+ st[1][1] = t1;
+ st[2][0] = s2;
+ st[2][1] = t2;
+ st[3][0] = s1;
+ st[3][1] = t2;
util_map_texcoords2d_onto_cubemap(surf->face,
/* pointer, stride in floats */
@@ -567,45 +575,29 @@ void util_blitter_clear(struct blitter_context *blitter,
blitter_restore_CSOs(ctx);
}
-void util_blitter_copy(struct blitter_context *blitter,
- struct pipe_surface *dst,
- unsigned dstx, unsigned dsty,
- struct pipe_surface *src,
- unsigned srcx, unsigned srcy,
- unsigned width, unsigned height,
- boolean ignore_stencil)
+static boolean
+is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2,
+ unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2)
+{
+ if (sx1 >= dx2 || sx2 <= dx1 || sy1 >= dy2 || sy2 <= dy1) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+static void util_blitter_do_copy(struct blitter_context *blitter,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ struct pipe_surface *src,
+ unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height,
+ boolean is_depth)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->pipe;
- struct pipe_screen *screen = pipe->screen;
struct pipe_framebuffer_state fb_state;
- boolean is_stencil, is_depth;
- unsigned dst_tex_usage;
-
- /* give up if textures are not set */
- assert(dst->texture && src->texture);
- if (!dst->texture || !src->texture)
- return;
-
- is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
- is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
- dst_tex_usage = is_depth || is_stencil ? PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
- PIPE_TEXTURE_USAGE_RENDER_TARGET;
- /* check if we can sample from and render to the surfaces */
- /* (assuming copying a stencil buffer is not possible) */
- if ((!ignore_stencil && is_stencil) ||
- !screen->is_format_supported(screen, dst->format, dst->texture->target,
- dst_tex_usage, 0) ||
- !screen->is_format_supported(screen, src->format, src->texture->target,
- PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
- util_surface_copy(pipe, FALSE, dst, dstx, dsty, src, srcx, srcy,
- width, height);
- return;
- }
-
- /* check whether the states are properly saved */
- blitter_check_saved_CSOs(ctx);
assert(blitter->saved_fb_state.nr_cbufs != ~0);
assert(blitter->saved_num_textures != ~0);
assert(blitter->saved_num_sampler_states != ~0);
@@ -663,6 +655,108 @@ void util_blitter_copy(struct blitter_context *blitter,
blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
blitter_draw_quad(ctx);
+
+}
+
+static void util_blitter_overlap_copy(struct blitter_context *blitter,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ struct pipe_surface *src,
+ unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+
+ struct pipe_texture texTemp;
+ struct pipe_texture *texture;
+ struct pipe_surface *tex_surf;
+
+ /* check whether the states are properly saved */
+ blitter_check_saved_CSOs(ctx);
+
+ memset(&texTemp, 0, sizeof(texTemp));
+ texTemp.target = PIPE_TEXTURE_2D;
+ texTemp.format = dst->texture->format; /* XXX verify supported by driver! */
+ texTemp.last_level = 0;
+ texTemp.width0 = width;
+ texTemp.height0 = height;
+ texTemp.depth0 = 1;
+
+ texture = screen->texture_create(screen, &texTemp);
+ if (!texture)
+ return;
+
+ tex_surf = screen->get_tex_surface(screen, texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* blit from the src to the temp */
+ util_blitter_do_copy(blitter, tex_surf, 0, 0,
+ src, srcx, srcy,
+ width, height,
+ FALSE);
+ util_blitter_do_copy(blitter, dst, dstx, dsty,
+ tex_surf, 0, 0,
+ width, height,
+ FALSE);
+ pipe_surface_reference(&tex_surf, NULL);
+ pipe_texture_reference(&texture, NULL);
+ blitter_restore_CSOs(ctx);
+}
+
+void util_blitter_copy(struct blitter_context *blitter,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ struct pipe_surface *src,
+ unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height,
+ boolean ignore_stencil)
+{
+ struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ boolean is_stencil, is_depth;
+ unsigned dst_tex_usage;
+
+ /* give up if textures are not set */
+ assert(dst->texture && src->texture);
+ if (!dst->texture || !src->texture)
+ return;
+
+ if (dst->texture == src->texture) {
+ if (is_overlap(srcx, srcx + width, srcy, srcy + height,
+ dstx, dstx + width, dsty, dsty + height)) {
+ util_blitter_overlap_copy(blitter, dst, dstx, dsty, src, srcx, srcy,
+ width, height);
+ return;
+ }
+ }
+
+ is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
+ is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
+ dst_tex_usage = is_depth || is_stencil ? PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
+ PIPE_TEXTURE_USAGE_RENDER_TARGET;
+
+ /* check if we can sample from and render to the surfaces */
+ /* (assuming copying a stencil buffer is not possible) */
+ if ((!ignore_stencil && is_stencil) ||
+ !screen->is_format_supported(screen, dst->format, dst->texture->target,
+ dst_tex_usage, 0) ||
+ !screen->is_format_supported(screen, src->format, src->texture->target,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ util_surface_copy(pipe, FALSE, dst, dstx, dsty, src, srcx, srcy,
+ width, height);
+ return;
+ }
+
+ /* check whether the states are properly saved */
+ blitter_check_saved_CSOs(ctx);
+ util_blitter_do_copy(blitter,
+ dst, dstx, dsty,
+ src, srcx, srcy,
+ width, height, is_depth);
blitter_restore_CSOs(ctx);
}
diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c
index 4110485fb19..e2e23c3cdd8 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.c
+++ b/src/gallium/auxiliary/util/u_draw_quad.c
@@ -61,6 +61,7 @@ util_draw_vertex_buffer(struct pipe_context *pipe,
/* tell pipe about the vertex attributes */
for (i = 0; i < num_attribs; i++) {
velements[i].src_offset = i * 4 * sizeof(float);
+ velements[i].instance_divisor = 0;
velements[i].vertex_buffer_index = 0;
velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
velements[i].nr_components = 4;
diff --git a/src/gallium/auxiliary/util/u_format.csv b/src/gallium/auxiliary/util/u_format.csv
index 9f16b42944e..01f7931aed1 100644
--- a/src/gallium/auxiliary/util/u_format.csv
+++ b/src/gallium/auxiliary/util/u_format.csv
@@ -62,10 +62,10 @@ PIPE_FORMAT_R16G16_SSCALED , array , 1, 1, s16 , s16 , , , xy01,
PIPE_FORMAT_R16G16B16_SSCALED , array , 1, 1, s16 , s16 , s16 , , xyz1, rgb
PIPE_FORMAT_R16G16B16A16_SSCALED , array , 1, 1, s16 , s16 , s16 , s16 , xyzw, rgb
PIPE_FORMAT_R8_UNORM , array , 1, 1, un8 , , , , x001, rgb
-PIPE_FORMAT_R8G8_UNORM , array , 1, 1, un8 , un8 , , , xy01, rgb
-PIPE_FORMAT_R8G8B8_UNORM , array , 1, 1, un8 , un8 , un8 , , xyz1, rgb
-PIPE_FORMAT_R8G8B8A8_UNORM , array , 1, 1, un8 , un8 , un8 , un8 , xyzw, rgb
-PIPE_FORMAT_R8G8B8X8_UNORM , array , 1, 1, un8 , un8 , un8 , un8 , xyz1, rgb
+PIPE_FORMAT_R8G8_UNORM , array , 1, 1, un8 , un8 , , , yx01, rgb
+PIPE_FORMAT_R8G8B8_UNORM , array , 1, 1, un8 , un8 , un8 , , zyx1, rgb
+PIPE_FORMAT_R8G8B8A8_UNORM , array , 1, 1, un8 , un8 , un8 , un8 , wzyx, rgb
+PIPE_FORMAT_R8G8B8X8_UNORM , array , 1, 1, un8 , un8 , un8 , un8 , wzy1, rgb
PIPE_FORMAT_R8_USCALED , array , 1, 1, u8 , , , , x001, rgb
PIPE_FORMAT_R8G8_USCALED , array , 1, 1, u8 , u8 , , , xy01, rgb
PIPE_FORMAT_R8G8B8_USCALED , array , 1, 1, u8 , u8 , u8 , , xyz1, rgb
diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h
index 43eb0153ee7..0ab53c75dd6 100644
--- a/src/gallium/auxiliary/util/u_pack_color.h
+++ b/src/gallium/auxiliary/util/u_pack_color.h
@@ -425,6 +425,8 @@ util_pack_z(enum pipe_format format, double z)
if (z == 1.0)
return 0xffffffff;
return (uint) (z * 0xffffffff);
+ case PIPE_FORMAT_Z32_FLOAT:
+ return (uint)z;
case PIPE_FORMAT_S8Z24_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
if (z == 1.0)
diff --git a/src/gallium/auxiliary/util/u_ringbuffer.c b/src/gallium/auxiliary/util/u_ringbuffer.c
new file mode 100644
index 00000000000..3f43a19e018
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_ringbuffer.c
@@ -0,0 +1,145 @@
+
+#include "pipe/p_thread.h"
+#include "pipe/p_defines.h"
+#include "util/u_ringbuffer.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+/* Generic ringbuffer:
+ */
+struct util_ringbuffer
+{
+ struct util_packet *buf;
+ unsigned mask;
+
+ /* Can this be done with atomic variables??
+ */
+ unsigned head;
+ unsigned tail;
+ pipe_condvar change;
+ pipe_mutex mutex;
+};
+
+
+struct util_ringbuffer *util_ringbuffer_create( unsigned dwords )
+{
+ struct util_ringbuffer *ring = CALLOC_STRUCT(util_ringbuffer);
+ if (ring == NULL)
+ return NULL;
+
+ assert(util_is_power_of_two(dwords));
+
+ ring->buf = MALLOC( dwords * sizeof(unsigned) );
+ if (ring->buf == NULL)
+ goto fail;
+
+ ring->mask = dwords - 1;
+
+ pipe_condvar_init(ring->change);
+ pipe_mutex_init(ring->mutex);
+ return ring;
+
+fail:
+ FREE(ring->buf);
+ FREE(ring);
+ return NULL;
+}
+
+void util_ringbuffer_destroy( struct util_ringbuffer *ring )
+{
+ pipe_condvar_destroy(ring->change);
+ pipe_mutex_destroy(ring->mutex);
+ FREE(ring->buf);
+ FREE(ring);
+}
+
+static INLINE unsigned util_ringbuffer_space( const struct util_ringbuffer *ring )
+{
+ return (ring->tail - (ring->head + 1)) & ring->mask;
+}
+
+void util_ringbuffer_enqueue( struct util_ringbuffer *ring,
+ const struct util_packet *packet )
+{
+ unsigned i;
+
+ /* XXX: over-reliance on mutexes, etc:
+ */
+ pipe_mutex_lock(ring->mutex);
+
+ /* Wait for free space:
+ */
+ while (util_ringbuffer_space(ring) < packet->dwords)
+ pipe_condvar_wait(ring->change, ring->mutex);
+
+ /* Copy data to ring:
+ */
+ for (i = 0; i < packet->dwords; i++) {
+
+ /* Copy all dwords of the packet. Note we're abusing the
+ * typesystem a little - we're being passed a pointer to
+ * something, but probably not an array of packet structs:
+ */
+ ring->buf[ring->head] = packet[i];
+ ring->head++;
+ ring->head &= ring->mask;
+ }
+
+ /* Signal change:
+ */
+ pipe_condvar_signal(ring->change);
+ pipe_mutex_unlock(ring->mutex);
+}
+
+enum pipe_error util_ringbuffer_dequeue( struct util_ringbuffer *ring,
+ struct util_packet *packet,
+ unsigned max_dwords,
+ boolean wait )
+{
+ const struct util_packet *ring_packet;
+ unsigned i;
+ int ret = PIPE_OK;
+
+ /* XXX: over-reliance on mutexes, etc:
+ */
+ pipe_mutex_lock(ring->mutex);
+
+ /* Wait for free space:
+ */
+ if (wait) {
+ while (util_ringbuffer_space(ring) == 0)
+ pipe_condvar_wait(ring->change, ring->mutex);
+ }
+ else {
+ if (util_ringbuffer_space(ring) == 0) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ }
+
+ ring_packet = &ring->buf[ring->tail];
+
+ /* Both of these are considered bugs. Raise an assert on debug builds.
+ */
+ if (ring_packet->dwords > ring->mask + 1 - util_ringbuffer_space(ring) ||
+ ring_packet->dwords > max_dwords) {
+ assert(0);
+ ret = PIPE_ERROR_BAD_INPUT;
+ goto out;
+ }
+
+ /* Copy data from ring:
+ */
+ for (i = 0; i < ring_packet->dwords; i++) {
+ packet[i] = ring->buf[ring->tail];
+ ring->tail++;
+ ring->tail &= ring->mask;
+ }
+
+out:
+ /* Signal change:
+ */
+ pipe_condvar_signal(ring->change);
+ pipe_mutex_unlock(ring->mutex);
+ return ret;
+}
diff --git a/src/gallium/auxiliary/util/u_ringbuffer.h b/src/gallium/auxiliary/util/u_ringbuffer.h
new file mode 100644
index 00000000000..85f0ad6c1f6
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_ringbuffer.h
@@ -0,0 +1,29 @@
+
+#ifndef UTIL_RINGBUFFER_H
+#define UTIL_RINGBUFFER_H
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_defines.h" /* only for pipe_error! */
+
+/* Generic header
+ */
+struct util_packet {
+ unsigned dwords:8;
+ unsigned data24:24;
+};
+
+struct util_ringbuffer;
+
+struct util_ringbuffer *util_ringbuffer_create( unsigned dwords );
+
+void util_ringbuffer_destroy( struct util_ringbuffer *ring );
+
+void util_ringbuffer_enqueue( struct util_ringbuffer *ring,
+ const struct util_packet *packet );
+
+enum pipe_error util_ringbuffer_dequeue( struct util_ringbuffer *ring,
+ struct util_packet *packet,
+ unsigned max_dwords,
+ boolean wait );
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c
index 1ba82bb21f0..f9936eb1cb2 100644
--- a/src/gallium/auxiliary/util/u_tile.c
+++ b/src/gallium/auxiliary/util/u_tile.c
@@ -1357,7 +1357,10 @@ pipe_put_tile_rgba(struct pipe_transfer *pt,
/*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
break;
default:
- debug_printf("%s: unsupported format %s\n", __FUNCTION__, pf_name(format));
+ util_format_write_4f(format,
+ p, src_stride * sizeof(float),
+ packed, util_format_get_stride(format, w),
+ 0, 0, w, h);
}
pipe_put_tile_raw(pt, x, y, w, h, packed, 0);
diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c
index fc2a1c59a6b..a524e2fdfb3 100644
--- a/src/gallium/auxiliary/vl/vl_compositor.c
+++ b/src/gallium/auxiliary/vl/vl_compositor.c
@@ -316,6 +316,7 @@ init_buffers(struct vl_compositor *c)
pipe_buffer_unmap(c->pipe->screen, c->vertex_bufs[0].buffer);
c->vertex_elems[0].src_offset = 0;
+ c->vertex_elems[0].instance_divisor = 0;
c->vertex_elems[0].vertex_buffer_index = 0;
c->vertex_elems[0].nr_components = 2;
c->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
@@ -345,6 +346,7 @@ init_buffers(struct vl_compositor *c)
pipe_buffer_unmap(c->pipe->screen, c->vertex_bufs[1].buffer);
c->vertex_elems[1].src_offset = 0;
+ c->vertex_elems[1].instance_divisor = 0;
c->vertex_elems[1].vertex_buffer_index = 1;
c->vertex_elems[1].nr_components = 2;
c->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
@@ -353,7 +355,7 @@ init_buffers(struct vl_compositor *c)
* Create our vertex shader's constant buffer
* Const buffer contains scaling and translation vectors
*/
- c->vs_const_buf.buffer = pipe_buffer_create
+ c->vs_const_buf = pipe_buffer_create
(
c->pipe->screen,
1,
@@ -365,7 +367,7 @@ init_buffers(struct vl_compositor *c)
* Create our fragment shader's constant buffer
* Const buffer contains the color conversion matrix and bias vectors
*/
- c->fs_const_buf.buffer = pipe_buffer_create
+ c->fs_const_buf = pipe_buffer_create
(
c->pipe->screen,
1,
@@ -390,8 +392,8 @@ cleanup_buffers(struct vl_compositor *c)
for (i = 0; i < 2; ++i)
pipe_buffer_reference(&c->vertex_bufs[i].buffer, NULL);
- pipe_buffer_reference(&c->vs_const_buf.buffer, NULL);
- pipe_buffer_reference(&c->fs_const_buf.buffer, NULL);
+ pipe_buffer_reference(&c->vs_const_buf, NULL);
+ pipe_buffer_reference(&c->fs_const_buf, NULL);
}
bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe)
@@ -483,13 +485,13 @@ void vl_compositor_render(struct vl_compositor *compositor,
compositor->pipe->bind_fs_state(compositor->pipe, compositor->fragment_shader);
compositor->pipe->set_vertex_buffers(compositor->pipe, 2, compositor->vertex_bufs);
compositor->pipe->set_vertex_elements(compositor->pipe, 2, compositor->vertex_elems);
- compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_VERTEX, 0, &compositor->vs_const_buf);
- compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_FRAGMENT, 0, &compositor->fs_const_buf);
+ compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_VERTEX, 0, compositor->vs_const_buf);
+ compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_FRAGMENT, 0, compositor->fs_const_buf);
vs_consts = pipe_buffer_map
(
compositor->pipe->screen,
- compositor->vs_const_buf.buffer,
+ compositor->vs_const_buf,
PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
);
@@ -511,7 +513,7 @@ void vl_compositor_render(struct vl_compositor *compositor,
vs_consts->src_trans.z = 0;
vs_consts->src_trans.w = 0;
- pipe_buffer_unmap(compositor->pipe->screen, compositor->vs_const_buf.buffer);
+ pipe_buffer_unmap(compositor->pipe->screen, compositor->vs_const_buf);
compositor->pipe->draw_arrays(compositor->pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
compositor->pipe->flush(compositor->pipe, PIPE_FLUSH_RENDER_CACHE, fence);
@@ -525,10 +527,10 @@ void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float
memcpy
(
- pipe_buffer_map(compositor->pipe->screen, compositor->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ pipe_buffer_map(compositor->pipe->screen, compositor->fs_const_buf, PIPE_BUFFER_USAGE_CPU_WRITE),
mat,
sizeof(struct fragment_shader_consts)
);
- pipe_buffer_unmap(compositor->pipe->screen, compositor->fs_const_buf.buffer);
+ pipe_buffer_unmap(compositor->pipe->screen, compositor->fs_const_buf);
}
diff --git a/src/gallium/auxiliary/vl/vl_compositor.h b/src/gallium/auxiliary/vl/vl_compositor.h
index f441901a751..6a9a3fd7af1 100644
--- a/src/gallium/auxiliary/vl/vl_compositor.h
+++ b/src/gallium/auxiliary/vl/vl_compositor.h
@@ -47,7 +47,7 @@ struct vl_compositor
struct pipe_scissor_state scissor;
struct pipe_vertex_buffer vertex_bufs[2];
struct pipe_vertex_element vertex_elems[2];
- struct pipe_constant_buffer vs_const_buf, fs_const_buf;
+ struct pipe_buffer *vs_const_buf, *fs_const_buf;
};
bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe);
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c
index caf581aca60..e43187545c5 100644
--- a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c
+++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c
@@ -891,53 +891,61 @@ init_buffers(struct vl_mpeg12_mc_renderer *r)
/* Position element */
r->vertex_elems[0].src_offset = 0;
+ r->vertex_elems[0].instance_divisor = 0;
r->vertex_elems[0].vertex_buffer_index = 0;
r->vertex_elems[0].nr_components = 2;
r->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
/* Luma, texcoord element */
r->vertex_elems[1].src_offset = sizeof(struct vertex2f);
+ r->vertex_elems[1].instance_divisor = 0;
r->vertex_elems[1].vertex_buffer_index = 0;
r->vertex_elems[1].nr_components = 2;
r->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
/* Chroma Cr texcoord element */
r->vertex_elems[2].src_offset = sizeof(struct vertex2f) * 2;
+ r->vertex_elems[2].instance_divisor = 0;
r->vertex_elems[2].vertex_buffer_index = 0;
r->vertex_elems[2].nr_components = 2;
r->vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT;
/* Chroma Cb texcoord element */
r->vertex_elems[3].src_offset = sizeof(struct vertex2f) * 3;
+ r->vertex_elems[3].instance_divisor = 0;
r->vertex_elems[3].vertex_buffer_index = 0;
r->vertex_elems[3].nr_components = 2;
r->vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT;
/* First ref surface top field texcoord element */
r->vertex_elems[4].src_offset = 0;
+ r->vertex_elems[4].instance_divisor = 0;
r->vertex_elems[4].vertex_buffer_index = 1;
r->vertex_elems[4].nr_components = 2;
r->vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT;
/* First ref surface bottom field texcoord element */
r->vertex_elems[5].src_offset = sizeof(struct vertex2f);
+ r->vertex_elems[5].instance_divisor = 0;
r->vertex_elems[5].vertex_buffer_index = 1;
r->vertex_elems[5].nr_components = 2;
r->vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT;
/* Second ref surface top field texcoord element */
r->vertex_elems[6].src_offset = 0;
+ r->vertex_elems[6].instance_divisor = 0;
r->vertex_elems[6].vertex_buffer_index = 2;
r->vertex_elems[6].nr_components = 2;
r->vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT;
/* Second ref surface bottom field texcoord element */
r->vertex_elems[7].src_offset = sizeof(struct vertex2f);
+ r->vertex_elems[7].instance_divisor = 0;
r->vertex_elems[7].vertex_buffer_index = 2;
r->vertex_elems[7].nr_components = 2;
r->vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT;
- r->vs_const_buf.buffer = pipe_buffer_create
+ r->vs_const_buf = pipe_buffer_create
(
r->pipe->screen,
DEFAULT_BUF_ALIGNMENT,
@@ -945,7 +953,7 @@ init_buffers(struct vl_mpeg12_mc_renderer *r)
sizeof(struct vertex_shader_consts)
);
- r->fs_const_buf.buffer = pipe_buffer_create
+ r->fs_const_buf = pipe_buffer_create
(
r->pipe->screen,
DEFAULT_BUF_ALIGNMENT,
@@ -954,11 +962,11 @@ init_buffers(struct vl_mpeg12_mc_renderer *r)
memcpy
(
- pipe_buffer_map(r->pipe->screen, r->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ pipe_buffer_map(r->pipe->screen, r->fs_const_buf, PIPE_BUFFER_USAGE_CPU_WRITE),
&fs_consts, sizeof(struct fragment_shader_consts)
);
- pipe_buffer_unmap(r->pipe->screen, r->fs_const_buf.buffer);
+ pipe_buffer_unmap(r->pipe->screen, r->fs_const_buf);
return true;
}
@@ -970,8 +978,8 @@ cleanup_buffers(struct vl_mpeg12_mc_renderer *r)
assert(r);
- pipe_buffer_reference(&r->vs_const_buf.buffer, NULL);
- pipe_buffer_reference(&r->fs_const_buf.buffer, NULL);
+ pipe_buffer_reference(&r->vs_const_buf, NULL);
+ pipe_buffer_reference(&r->fs_const_buf, NULL);
for (i = 0; i < 3; ++i)
pipe_buffer_reference(&r->vertex_bufs.all[i].buffer, NULL);
@@ -1284,19 +1292,19 @@ flush(struct vl_mpeg12_mc_renderer *r)
vs_consts = pipe_buffer_map
(
- r->pipe->screen, r->vs_const_buf.buffer,
+ r->pipe->screen, r->vs_const_buf,
PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
);
vs_consts->denorm.x = r->surface->width0;
vs_consts->denorm.y = r->surface->height0;
- pipe_buffer_unmap(r->pipe->screen, r->vs_const_buf.buffer);
+ pipe_buffer_unmap(r->pipe->screen, r->vs_const_buf);
r->pipe->set_constant_buffer(r->pipe, PIPE_SHADER_VERTEX, 0,
- &r->vs_const_buf);
+ r->vs_const_buf);
r->pipe->set_constant_buffer(r->pipe, PIPE_SHADER_FRAGMENT, 0,
- &r->fs_const_buf);
+ r->fs_const_buf);
if (num_macroblocks[MACROBLOCK_TYPE_INTRA] > 0) {
r->pipe->set_vertex_buffers(r->pipe, 1, r->vertex_bufs.all);
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h
index 64184337a06..f00b8c7b8b1 100644
--- a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h
+++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h
@@ -63,8 +63,8 @@ struct vl_mpeg12_mc_renderer
struct pipe_viewport_state viewport;
struct pipe_scissor_state scissor;
- struct pipe_constant_buffer vs_const_buf;
- struct pipe_constant_buffer fs_const_buf;
+ struct pipe_buffer *vs_const_buf;
+ struct pipe_buffer *fs_const_buf;
struct pipe_framebuffer_state fb_state;
struct pipe_vertex_element vertex_elems[8];
diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst
index 21f5f9111a0..d394f5b4f1b 100644
--- a/src/gallium/docs/source/context.rst
+++ b/src/gallium/docs/source/context.rst
@@ -33,7 +33,11 @@ This state describes how resources in various flavours (textures,
buffers, surfaces) are bound to the driver.
-* ``set_constant_buffer``
+* ``set_constant_buffer`` sets a constant buffer to be used for a given shader
+ type. index is used to indicate which buffer to set (some apis may allow
+ multiple ones to be set, and binding a specific one later, though drivers
+ are mostly restricted to the first one right now).
+
* ``set_framebuffer_state``
* ``set_fragment_sampler_textures``
* ``set_vertex_sampler_textures``
@@ -47,7 +51,6 @@ These pieces of state are too small, variable, and/or trivial to have CSO
objects. They all follow simple, one-method binding calls, e.g.
``set_edgeflags``.
-* ``set_edgeflags``
* ``set_blend_color``
* ``set_clip_state``
* ``set_polygon_stipple``
@@ -72,12 +75,67 @@ stencil-only clears of packed depth-stencil buffers.
Drawing
^^^^^^^
-``draw_arrays``
+``draw_arrays`` draws a specified primitive.
+
+This command is equivalent to calling ``draw_arrays_instanced``
+with ``startInstance`` set to 0 and ``instanceCount`` set to 1.
+
+``draw_elements`` draws a specified primitive using an optional
+index buffer.
-``draw_elements``
+This command is equivalent to calling ``draw_elements_instanced``
+with ``startInstance`` set to 0 and ``instanceCount`` set to 1.
``draw_range_elements``
+XXX: this is (probably) a temporary entrypoint, as the range
+information should be available from the vertex_buffer state.
+Using this to quickly evaluate a specialized path in the draw
+module.
+
+``draw_arrays_instanced`` draws multiple instances of the same primitive.
+
+This command is equivalent to calling ``draw_elements_instanced``
+with ``indexBuffer`` set to NULL and ``indexSize`` set to 0.
+
+``draw_elements_instanced`` draws multiple instances of the same primitive
+using an optional index buffer.
+
+For instanceID in the range between ``startInstance``
+and ``startInstance``+``instanceCount``-1, inclusive, draw a primitive
+specified by ``mode`` and sequential numbers in the range between ``start``
+and ``start``+``count``-1, inclusive.
+
+If ``indexBuffer`` is not NULL, it specifies an index buffer with index
+byte size of ``indexSize``. The sequential numbers are used to lookup
+the index buffer and the resulting indices in turn are used to fetch
+vertex attributes.
+
+If ``indexBuffer`` is NULL, the sequential numbers are used directly
+as indices to fetch vertex attributes.
+
+If a given vertex element has ``instance_divisor`` set to 0, it is said
+it contains per-vertex data and effective vertex attribute address needs
+to be recalculated for every index.
+
+ attribAddr = ``stride`` * index + ``src_offset``
+
+If a given vertex element has ``instance_divisor`` set to non-zero,
+it is said it contains per-instance data and effective vertex attribute
+address needs to recalculated for every ``instance_divisor``-th instance.
+
+ attribAddr = ``stride`` * instanceID / ``instance_divisor`` + ``src_offset``
+
+In the above formulas, ``src_offset`` is taken from the given vertex element
+and ``stride`` is taken from a vertex buffer associated with the given
+vertex element.
+
+The calculated attribAddr is used as an offset into the vertex buffer to
+fetch the attribute data.
+
+The value of ``instanceID`` can be read in a vertex shader through a system
+value register declared with INSTANCEID semantic name.
+
Queries
^^^^^^^
diff --git a/src/gallium/docs/source/distro.rst b/src/gallium/docs/source/distro.rst
index 33e846e33d2..a448203c6fa 100644
--- a/src/gallium/docs/source/distro.rst
+++ b/src/gallium/docs/source/distro.rst
@@ -118,6 +118,9 @@ Gallivm
Indices
^^^^^^^
+Tool for translating or generating element indices for element-based
+rendering.
+
Pipe Buffer Manager
^^^^^^^^^^^^^^^^^^^
@@ -127,12 +130,11 @@ Remote Debugger
Runtime Assembly Emission
^^^^^^^^^^^^^^^^^^^^^^^^^
-Surface Context Tracker
-^^^^^^^^^^^^^^^^^^^^^^^
-
TGSI
^^^^
+Basic utilities for manipulating TGSI streams.
+
Translate
^^^^^^^^^
diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h
index d5f5c7bbba8..aa29dcb3947 100644
--- a/src/gallium/drivers/cell/common.h
+++ b/src/gallium/drivers/cell/common.h
@@ -358,6 +358,7 @@ struct cell_spu_function_info
/** This is the object passed to spe_create_thread() */
+PIPE_ALIGN_TYPE(16,
struct cell_init_info
{
unsigned id;
@@ -370,7 +371,7 @@ struct cell_init_info
uint *buffer_status; /**< points at cell_context->buffer_status */
struct cell_spu_function_info *spu_functions;
-} ALIGN16_ATTRIB;
+});
#endif /* CELL_COMMON_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h
index 5c3188e7f9d..e402ed29220 100644
--- a/src/gallium/drivers/cell/ppu/cell_context.h
+++ b/src/gallium/drivers/cell/ppu/cell_context.h
@@ -89,7 +89,7 @@ struct cell_buffer_node;
*/
struct cell_buffer_list
{
- struct cell_fence fence ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) struct cell_fence fence;
struct cell_buffer_node *head;
};
@@ -115,7 +115,7 @@ struct cell_context
struct pipe_blend_color blend_color;
struct pipe_clip_state clip;
- struct pipe_constant_buffer constants[2];
+ struct pipe_buffer *constants[2];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
@@ -150,18 +150,18 @@ struct cell_context
/** Mapped constant buffers */
void *mapped_constants[PIPE_SHADER_TYPES];
- struct cell_spu_function_info spu_functions ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) struct cell_spu_function_info spu_functions;
uint num_cells, num_spus;
/** Buffers for command batches, vertex/index data */
uint buffer_size[CELL_NUM_BUFFERS];
- ubyte buffer[CELL_NUM_BUFFERS][CELL_BUFFER_SIZE] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) ubyte buffer[CELL_NUM_BUFFERS][CELL_BUFFER_SIZE];
int cur_batch; /**< which buffer is being filled w/ commands */
/** [4] to ensure 16-byte alignment for each status word */
- uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BUFFERS][4] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BUFFERS][4];
/** Associated with each command/batch buffer is a list of pipe_buffers
diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
index 3fa8b975d39..0a4da8ecc85 100644
--- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
+++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
@@ -51,17 +51,17 @@ cell_map_constant_buffers(struct cell_context *sp)
struct pipe_winsys *ws = sp->pipe.winsys;
uint i;
for (i = 0; i < 2; i++) {
- if (sp->constants[i].buffer && sp->constants[i].buffer->size) {
- sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i].buffer,
+ if (sp->constants[i] && sp->constants[i]->size) {
+ sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i],
PIPE_BUFFER_USAGE_CPU_READ);
cell_flush_buffer_range(sp, sp->mapped_constants[i],
- sp->constants[i].buffer->size);
+ sp->constants[i]->size);
}
}
draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX,
sp->mapped_constants[PIPE_SHADER_VERTEX],
- sp->constants[PIPE_SHADER_VERTEX].buffer->size);
+ sp->constants[PIPE_SHADER_VERTEX]->size);
}
static void
@@ -70,8 +70,8 @@ cell_unmap_constant_buffers(struct cell_context *sp)
struct pipe_winsys *ws = sp->pipe.winsys;
uint i;
for (i = 0; i < 2; i++) {
- if (sp->constants[i].buffer && sp->constants[i].buffer->size)
- ws->buffer_unmap(ws, sp->constants[i].buffer);
+ if (sp->constants[i] && sp->constants[i]->size)
+ ws->buffer_unmap(ws, sp->constants[i]);
sp->mapped_constants[i] = NULL;
}
}
diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c
index 5b87286d4c5..f1e1dcb9eb0 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_emit.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c
@@ -240,12 +240,12 @@ cell_emit_state(struct cell_context *cell)
if (cell->dirty & (CELL_NEW_FS_CONSTANTS)) {
const uint shader = PIPE_SHADER_FRAGMENT;
- const uint num_const = cell->constants[shader].buffer->size / sizeof(float);
+ const uint num_const = cell->constants[shader]->size / sizeof(float);
uint i, j;
float *buf = cell_batch_alloc16(cell, ROUNDUP16(32 + num_const * sizeof(float)));
uint32_t *ibuf = (uint32_t *) buf;
const float *constants = pipe_buffer_map(cell->pipe.screen,
- cell->constants[shader].buffer,
+ cell->constants[shader],
PIPE_BUFFER_USAGE_CPU_READ);
ibuf[0] = CELL_CMD_STATE_FS_CONSTANTS;
ibuf[4] = num_const;
@@ -253,7 +253,7 @@ cell_emit_state(struct cell_context *cell)
for (i = 0; i < num_const; i++) {
buf[j++] = constants[i];
}
- pipe_buffer_unmap(cell->pipe.screen, cell->constants[shader].buffer);
+ pipe_buffer_unmap(cell->pipe.screen, cell->constants[shader]);
}
if (cell->dirty & (CELL_NEW_FRAMEBUFFER |
diff --git a/src/gallium/drivers/cell/ppu/cell_state_shader.c b/src/gallium/drivers/cell/ppu/cell_state_shader.c
index 6568c784fec..1b09cf7f7d7 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_shader.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_shader.c
@@ -183,7 +183,7 @@ cell_delete_vs_state(struct pipe_context *pipe, void *vs)
static void
cell_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct cell_context *cell = cell_context(pipe);
@@ -193,7 +193,7 @@ cell_set_constant_buffer(struct pipe_context *pipe,
draw_flush(cell->draw);
/* note: reference counting */
- pipe_buffer_reference(&cell->constants[shader].buffer, buf->buffer);
+ pipe_buffer_reference(&cell->constants[shader], buf);
if (shader == PIPE_SHADER_VERTEX)
cell->dirty |= CELL_NEW_VS_CONSTANTS;
diff --git a/src/gallium/drivers/cell/spu/spu_command.c b/src/gallium/drivers/cell/spu/spu_command.c
index 12b855a3db2..55bd85bde2b 100644
--- a/src/gallium/drivers/cell/spu/spu_command.c
+++ b/src/gallium/drivers/cell/spu/spu_command.c
@@ -53,8 +53,7 @@ struct spu_vs_context draw;
/**
* Buffers containing dynamically generated SPU code:
*/
-static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS]
- ALIGN16_ATTRIB;
+PIPE_ALIGN_VAR(16) static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS];
@@ -543,7 +542,7 @@ cmd_batch(uint opcode)
{
const uint buf = (opcode >> 8) & 0xff;
uint size = (opcode >> 16);
- qword buffer[CELL_BUFFER_SIZE / 16] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) qword buffer[CELL_BUFFER_SIZE / 16];
const unsigned usize = ROUNDUP16(size) / sizeof(buffer[0]);
uint pos;
diff --git a/src/gallium/drivers/cell/spu/spu_exec.c b/src/gallium/drivers/cell/spu/spu_exec.c
index d86d8e09a51..d2166a49016 100644
--- a/src/gallium/drivers/cell/spu/spu_exec.c
+++ b/src/gallium/drivers/cell/spu/spu_exec.c
@@ -1839,10 +1839,11 @@ spu_exec_machine_run( struct spu_exec_machine *mach )
/* execute declarations (interpolants) */
if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) {
for (i = 0; i < mach->NumDeclarations; i++) {
+ PIPE_ALIGN_VAR(16)
union {
struct tgsi_full_declaration decl;
qword buffer[ROUNDUP16(sizeof(struct tgsi_full_declaration)) / 16];
- } d ALIGN16_ATTRIB;
+ } d;
unsigned ea = (unsigned) (mach->Declarations + pc);
spu_dcache_fetch_unaligned(d.buffer, ea, sizeof(d.decl));
@@ -1853,10 +1854,11 @@ spu_exec_machine_run( struct spu_exec_machine *mach )
/* execute instructions, until pc is set to -1 */
while (pc != -1) {
+ PIPE_ALIGN_VAR(16)
union {
struct tgsi_full_instruction inst;
qword buffer[ROUNDUP16(sizeof(struct tgsi_full_instruction)) / 16];
- } i ALIGN16_ATTRIB;
+ } i;
unsigned ea = (unsigned) (mach->Instructions + pc);
spu_dcache_fetch_unaligned(i.buffer, ea, sizeof(i.inst));
diff --git a/src/gallium/drivers/cell/spu/spu_exec.h b/src/gallium/drivers/cell/spu/spu_exec.h
index 86056799405..0ca92af248d 100644
--- a/src/gallium/drivers/cell/spu/spu_exec.h
+++ b/src/gallium/drivers/cell/spu/spu_exec.h
@@ -98,9 +98,9 @@ struct spu_exec_machine
* 4 internal temporaries
* 1 address
*/
+ PIPE_ALIGN_VAR(16)
struct spu_exec_vector Temps[TGSI_EXEC_NUM_TEMPS
- + TGSI_EXEC_NUM_TEMP_EXTRAS + 1]
- ALIGN16_ATTRIB;
+ + TGSI_EXEC_NUM_TEMP_EXTRAS + 1];
struct spu_exec_vector *Addrs;
diff --git a/src/gallium/drivers/cell/spu/spu_funcs.c b/src/gallium/drivers/cell/spu/spu_funcs.c
index ff3d609d258..98919c43ffc 100644
--- a/src/gallium/drivers/cell/spu/spu_funcs.c
+++ b/src/gallium/drivers/cell/spu/spu_funcs.c
@@ -144,7 +144,7 @@ export_func(struct cell_spu_function_info *spu_functions,
void
return_function_info(void)
{
- struct cell_spu_function_info funcs ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) struct cell_spu_function_info funcs;
int tag = TAG_MISC;
ASSERT(sizeof(funcs) == 256); /* must be multiple of 16 bytes */
diff --git a/src/gallium/drivers/cell/spu/spu_main.h b/src/gallium/drivers/cell/spu/spu_main.h
index 33767e7c51d..b18f4c22ef1 100644
--- a/src/gallium/drivers/cell/spu/spu_main.h
+++ b/src/gallium/drivers/cell/spu/spu_main.h
@@ -93,6 +93,7 @@ typedef vector unsigned int (*spu_fragment_program_func)(vector float *inputs,
vector float *constants);
+PIPE_ALIGN_TYPE(16,
struct spu_framebuffer
{
void *color_start; /**< addr of color surface in main memory */
@@ -107,10 +108,11 @@ struct spu_framebuffer
uint zsize; /**< 0, 2 or 4 bytes per Z */
float zscale; /**< 65535.0, 2^24-1 or 2^32-1 */
-} ALIGN16_ATTRIB;
+});
/** per-texture level info */
+PIPE_ALIGN_TYPE(16,
struct spu_texture_level
{
void *start;
@@ -123,20 +125,22 @@ struct spu_texture_level
vector signed int mask_s, mask_t, mask_r;
/** texcoord clamp limits */
vector signed int max_s, max_t, max_r;
-} ALIGN16_ATTRIB;
+});
+PIPE_ALIGN_TYPE(16,
struct spu_texture
{
struct spu_texture_level level[CELL_MAX_TEXTURE_LEVELS];
uint max_level;
uint target; /**< PIPE_TEXTURE_x */
-} ALIGN16_ATTRIB;
+});
/**
* All SPU global/context state will be in a singleton object of this type:
*/
+PIPE_ALIGN_TYPE(16,
struct spu_global
{
/** One-time init/constant info */
@@ -155,8 +159,8 @@ struct spu_global
struct vertex_info vertex_info;
/** Current color and Z tiles */
- tile_t ctile ALIGN16_ATTRIB;
- tile_t ztile ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) tile_t ctile;
+ PIPE_ALIGN_VAR(16) tile_t ztile;
/** Read depth/stencil tiles? */
boolean read_depth_stencil;
@@ -165,8 +169,8 @@ struct spu_global
ubyte cur_ctile_status, cur_ztile_status;
/** Status of all tiles in framebuffer */
- ubyte ctile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE] ALIGN16_ATTRIB;
- ubyte ztile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) ubyte ctile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE];
+ PIPE_ALIGN_VAR(16) ubyte ztile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE];
/** Current fragment ops machine code, at 8-byte boundary */
uint *fragment_ops_code;
@@ -175,7 +179,7 @@ struct spu_global
spu_fragment_ops_func fragment_ops[2];
/** Current fragment program machine code, at 8-byte boundary */
- uint fragment_program_code[SPU_MAX_FRAGMENT_PROGRAM_INSTS] ALIGN8_ATTRIB;
+ PIPE_ALIGN_VAR(8) uint fragment_program_code[SPU_MAX_FRAGMENT_PROGRAM_INSTS];
/** Current fragment ops function */
spu_fragment_program_func fragment_program;
@@ -187,7 +191,7 @@ struct spu_global
/** Fragment program constants */
vector float constants[4 * CELL_MAX_CONSTANTS];
-} ALIGN16_ATTRIB;
+});
extern struct spu_global spu;
diff --git a/src/gallium/drivers/cell/spu/spu_render.c b/src/gallium/drivers/cell/spu/spu_render.c
index 5ffb7073abf..14987e3c3a2 100644
--- a/src/gallium/drivers/cell/spu/spu_render.c
+++ b/src/gallium/drivers/cell/spu/spu_render.c
@@ -169,7 +169,7 @@ void
cmd_render(const struct cell_command_render *render, uint *pos_incr)
{
/* we'll DMA into these buffers */
- ubyte vertex_data[CELL_BUFFER_SIZE] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) ubyte vertex_data[CELL_BUFFER_SIZE];
const uint vertex_size = render->vertex_size; /* in bytes */
/*const*/ uint total_vertex_bytes = render->num_verts * vertex_size;
uint index_bytes;
diff --git a/src/gallium/drivers/cell/spu/spu_vertex_fetch.c b/src/gallium/drivers/cell/spu/spu_vertex_fetch.c
index 03375d84a57..087963960df 100644
--- a/src/gallium/drivers/cell/spu/spu_vertex_fetch.c
+++ b/src/gallium/drivers/cell/spu/spu_vertex_fetch.c
@@ -43,7 +43,8 @@ typedef void (*spu_fetch_func)(qword *out, const qword *in,
const qword *shuffle_data);
-static const qword fetch_shuffle_data[5] ALIGN16_ATTRIB = {
+PIPE_ALIGN_VAR(16) static const qword
+fetch_shuffle_data[5] = {
/* Shuffle used by CVT_64_FLOAT
*/
{
@@ -110,7 +111,7 @@ static void generic_vertex_fetch(struct spu_vs_context *draw,
unsigned idx;
const unsigned bytes_per_entry = draw->vertex_fetch.size[attr];
const unsigned quads_per_entry = (bytes_per_entry + 15) / 16;
- qword in[2 * 4] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) qword in[2 * 4];
/* Fetch four attributes for four vertices.
diff --git a/src/gallium/drivers/cell/spu/spu_vertex_shader.c b/src/gallium/drivers/cell/spu/spu_vertex_shader.c
index fbe5b34d397..3e9804bf8ee 100644
--- a/src/gallium/drivers/cell/spu/spu_vertex_shader.c
+++ b/src/gallium/drivers/cell/spu/spu_vertex_shader.c
@@ -107,8 +107,8 @@ run_vertex_program(struct spu_vs_context *draw,
struct spu_exec_machine *machine = &draw->machine;
unsigned int j;
- ALIGN16_DECL(struct spu_exec_vector, inputs, PIPE_MAX_ATTRIBS);
- ALIGN16_DECL(struct spu_exec_vector, outputs, PIPE_MAX_ATTRIBS);
+ PIPE_ALIGN_VAR(16) struct spu_exec_vector inputs[PIPE_MAX_ATTRIBS];
+ PIPE_ALIGN_VAR(16) struct spu_exec_vector outputs[PIPE_MAX_ATTRIBS];
const float *scale = draw->viewport.scale;
const float *trans = draw->viewport.translate;
@@ -119,8 +119,8 @@ run_vertex_program(struct spu_vs_context *draw,
ASSERT_ALIGN16(draw->constants);
machine->Consts = (float (*)[4]) draw->constants;
- machine->Inputs = ALIGN16_ASSIGN(inputs);
- machine->Outputs = ALIGN16_ASSIGN(outputs);
+ machine->Inputs = inputs;
+ machine->Outputs = outputs;
spu_vertex_fetch( draw, machine, elts, count );
@@ -132,8 +132,9 @@ run_vertex_program(struct spu_vs_context *draw,
for (j = 0; j < count; j++) {
unsigned slot;
float x, y, z, w;
+ PIPE_ALIGN_VAR(16)
unsigned char buffer[sizeof(struct vertex_header)
- + MAX_VERTEX_SIZE] ALIGN16_ATTRIB;
+ + MAX_VERTEX_SIZE];
struct vertex_header *const tmpOut =
(struct vertex_header *) buffer;
const unsigned vert_size = ROUNDUP16(sizeof(struct vertex_header)
@@ -186,8 +187,8 @@ run_vertex_program(struct spu_vs_context *draw,
}
-unsigned char immediates[(sizeof(float) * 4 * TGSI_EXEC_NUM_IMMEDIATES) + 32]
- ALIGN16_ATTRIB;
+PIPE_ALIGN_VAR(16) unsigned char
+immediates[(sizeof(float) * 4 * TGSI_EXEC_NUM_IMMEDIATES) + 32]);
void
diff --git a/src/gallium/drivers/failover/fo_context.h b/src/gallium/drivers/failover/fo_context.h
index 149393712a3..191a44c3dfc 100644
--- a/src/gallium/drivers/failover/fo_context.h
+++ b/src/gallium/drivers/failover/fo_context.h
@@ -125,7 +125,7 @@ failover_context( struct pipe_context *pipe )
void
failover_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf);
+ struct pipe_buffer *buf);
#endif /* FO_CONTEXT_H */
diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c
index 3f5f5560323..d6ec4d13136 100644
--- a/src/gallium/drivers/failover/fo_state.c
+++ b/src/gallium/drivers/failover/fo_state.c
@@ -495,7 +495,7 @@ failover_set_vertex_elements(struct pipe_context *pipe,
void
failover_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct failover_context *failover = failover_context(pipe);
diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h
index 234b441ce6e..37cbd56036b 100644
--- a/src/gallium/drivers/i915/i915_context.h
+++ b/src/gallium/drivers/i915/i915_context.h
@@ -233,7 +233,8 @@ struct i915_context
struct pipe_blend_color blend_color;
struct pipe_clip_state clip;
- struct pipe_constant_buffer constants[PIPE_SHADER_TYPES];
+ /* XXX unneded */
+ struct pipe_buffer *constants[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c
index 5f5b6f8e185..0fab6e1bc36 100644
--- a/src/gallium/drivers/i915/i915_state.c
+++ b/src/gallium/drivers/i915/i915_state.c
@@ -518,7 +518,7 @@ static void i915_delete_vs_state(struct pipe_context *pipe, void *shader)
static void i915_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct i915_context *i915 = i915_context(pipe);
struct pipe_screen *screen = pipe->screen;
@@ -538,13 +538,13 @@ static void i915_set_constant_buffer(struct pipe_context *pipe,
*/
if (buf) {
void *mapped;
- if (buf->buffer && buf->buffer->size &&
- (mapped = pipe_buffer_map(screen, buf->buffer,
+ if (buf->size &&
+ (mapped = pipe_buffer_map(screen, buf,
PIPE_BUFFER_USAGE_CPU_READ))) {
- memcpy(i915->current.constants[shader], mapped, buf->buffer->size);
- pipe_buffer_unmap(screen, buf->buffer);
+ memcpy(i915->current.constants[shader], mapped, buf->size);
+ pipe_buffer_unmap(screen, buf);
i915->current.num_user_constants[shader]
- = buf->buffer->size / (4 * sizeof(float));
+ = buf->size / (4 * sizeof(float));
}
else {
i915->current.num_user_constants[shader] = 0;
diff --git a/src/gallium/drivers/i965/brw_pipe_shader.c b/src/gallium/drivers/i965/brw_pipe_shader.c
index bb32d90e331..e389587f3e1 100644
--- a/src/gallium/drivers/i965/brw_pipe_shader.c
+++ b/src/gallium/drivers/i965/brw_pipe_shader.c
@@ -262,7 +262,7 @@ static void brw_delete_vs_state( struct pipe_context *pipe, void *prog )
static void brw_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct brw_context *brw = brw_context(pipe);
@@ -270,13 +270,13 @@ static void brw_set_constant_buffer(struct pipe_context *pipe,
if (shader == PIPE_SHADER_FRAGMENT) {
pipe_buffer_reference( &brw->curr.fragment_constants,
- buf->buffer );
+ buf );
brw->state.dirty.mesa |= PIPE_NEW_FRAGMENT_CONSTANTS;
}
else {
pipe_buffer_reference( &brw->curr.vertex_constants,
- buf->buffer );
+ buf );
brw->state.dirty.mesa |= PIPE_NEW_VERTEX_CONSTANTS;
}
diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c
index 9f5b4e63236..f9063d90fb1 100644
--- a/src/gallium/drivers/identity/id_context.c
+++ b/src/gallium/drivers/identity/id_context.c
@@ -404,17 +404,17 @@ static void
identity_set_constant_buffer(struct pipe_context *_pipe,
uint shader,
uint index,
- const struct pipe_constant_buffer *_buffer)
+ struct pipe_buffer *_buffer)
{
struct identity_context *id_pipe = identity_context(_pipe);
struct pipe_context *pipe = id_pipe->pipe;
- struct pipe_constant_buffer unwrapped_buffer;
- struct pipe_constant_buffer *buffer = NULL;
+ struct pipe_buffer *unwrapped_buffer;
+ struct pipe_buffer *buffer = NULL;
- /* unwrap the input state */
+ /* XXX hmm? unwrap the input state */
if (_buffer) {
- unwrapped_buffer.buffer = identity_buffer_unwrap(_buffer->buffer);
- buffer = &unwrapped_buffer;
+ unwrapped_buffer = identity_buffer_unwrap(_buffer);
+ buffer = unwrapped_buffer;
}
pipe->set_constant_buffer(pipe,
diff --git a/src/gallium/drivers/llvmpipe/README b/src/gallium/drivers/llvmpipe/README
index 0c3f00fd58f..72d9f39658f 100644
--- a/src/gallium/drivers/llvmpipe/README
+++ b/src/gallium/drivers/llvmpipe/README
@@ -59,27 +59,16 @@ Requirements
See /proc/cpuinfo to know what your CPU supports.
- - LLVM 2.5 or greater. LLVM 2.6 is preferred.
+ - LLVM 2.6.
- On Debian based distributions do:
+ For Linux, on a recent Debian based distribution do:
aptitude install llvm-dev
- There is a typo in one of the llvm 2.5 headers, that may cause compilation
- errors. To fix it apply the change:
-
- --- /usr/include/llvm-c/Core.h.orig 2009-08-10 15:38:54.000000000 +0100
- +++ /usr/include/llvm-c/Core.h 2009-08-10 15:38:25.000000000 +0100
- @@ -831,7 +831,7 @@
- template<typename T>
- inline T **unwrap(LLVMValueRef *Vals, unsigned Length) {
- #if DEBUG
- - for (LLVMValueRef *I = Vals, E = Vals + Length; I != E; ++I)
- + for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I)
- cast<T>(*I);
- #endif
- return reinterpret_cast<T**>(Vals);
-
+ For Windows download pre-built MSVC 9.0 or MinGW binaries from
+ http://people.freedesktop.org/~jrfonseca/llvm/ and set the LLVM environment
+ variable to the extracted path.
+
- scons (optional)
- udis86, http://udis86.sourceforge.net/ (optional):
@@ -95,9 +84,9 @@ Requirements
Building
========
-To build everything invoke scons as:
+To build everything on Linux invoke scons as:
- scons debug=yes statetrackers=mesa drivers=llvmpipe winsys=xlib dri=false -k
+ scons debug=yes statetrackers=mesa drivers=trace,llvmpipe winsys=xlib dri=false
Alternatively, you can build it with GNU make, if you prefer, by invoking it as
@@ -105,12 +94,15 @@ Alternatively, you can build it with GNU make, if you prefer, by invoking it as
but the rest of these instructions assume that scons is used.
+For windows is everything the except except the winsys:
+
+ scons debug=yes statetrackers=mesa drivers=trace,llvmpipe winsys=gdi dri=false
Using
=====
-Building will create a drop-in alternative for libGL.so. To use it set the
-environment variables:
+On Linux, building will create a drop-in alternative for libGL.so. To use it
+set the environment variables:
export LD_LIBRARY_PATH=$PWD/build/linux-x86_64-debug/lib:$LD_LIBRARY_PATH
@@ -121,6 +113,11 @@ or
For performance evaluation pass debug=no to scons, and use the corresponding
lib directory without the "-debug" suffix.
+On Windows, building will create a drop-in alternative for opengl32.dll. To use
+it put it in the same directory as the application. It can also be used by
+replacing the native ICD driver, but it's quite an advanced usage, so if you
+need to ask, don't even try it.
+
Unit testing
============
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp b/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp
index d3f78c06d92..6e79438ead0 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp
+++ b/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp
@@ -59,3 +59,17 @@ LLVMInitializeNativeTarget(void)
#endif
+
+
+/*
+ * Hack to allow the linking of release LLVM static libraries on a debug build.
+ *
+ * See also:
+ * - http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/7234ea2b-0042-42ed-b4e2-5d8644dfb57d
+ */
+#if defined(_MSC_VER) && defined(_DEBUG)
+#include <crtdefs.h>
+extern "C" {
+ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) {}
+}
+#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c
index bd549d4028b..c5b00f8e23f 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.c
+++ b/src/gallium/drivers/llvmpipe/lp_context.c
@@ -74,8 +74,8 @@ static void llvmpipe_destroy( struct pipe_context *pipe )
}
for (i = 0; i < Elements(llvmpipe->constants); i++) {
- if (llvmpipe->constants[i].buffer) {
- pipe_buffer_reference(&llvmpipe->constants[i].buffer, NULL);
+ if (llvmpipe->constants[i]) {
+ pipe_buffer_reference(&llvmpipe->constants[i], NULL);
}
}
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index 5390a713699..3af7b62a53b 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -62,7 +62,7 @@ struct llvmpipe_context {
/** Other rendering state */
struct pipe_blend_color blend_color;
struct pipe_clip_state clip;
- struct pipe_constant_buffer constants[PIPE_SHADER_TYPES];
+ struct pipe_buffer *constants[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index 21ebfa7ca91..e4c56f153fc 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -86,7 +86,7 @@ struct lp_rast_shader_inputs {
float (*dady)[4];
/* edge/step info for 3 edges and 4x4 block of pixels */
- int ALIGN16_ATTRIB step[3][16];
+ PIPE_ALIGN_VAR(16) int step[3][16];
};
@@ -121,7 +121,7 @@ struct lp_rast_triangle {
int c1, c2, c3;
/* inputs for the shader */
- struct lp_rast_shader_inputs ALIGN16_ATTRIB inputs;
+ PIPE_ALIGN_VAR(16) struct lp_rast_shader_inputs inputs;
};
diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h
index 224b6e523c3..4242653c909 100644
--- a/src/gallium/drivers/llvmpipe/lp_state.h
+++ b/src/gallium/drivers/llvmpipe/lp_state.h
@@ -162,7 +162,7 @@ void llvmpipe_set_clip_state( struct pipe_context *,
void llvmpipe_set_constant_buffer(struct pipe_context *,
uint shader, uint index,
- const struct pipe_constant_buffer *buf);
+ struct pipe_buffer *buf);
void *llvmpipe_create_fs_state(struct pipe_context *,
const struct pipe_shader_state *);
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index 28af477914c..bdd906e1a73 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -180,7 +180,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
if (llvmpipe->dirty & LP_NEW_CONSTANTS)
lp_setup_set_fs_constants(llvmpipe->setup,
- llvmpipe->constants[PIPE_SHADER_FRAGMENT].buffer);
+ llvmpipe->constants[PIPE_SHADER_FRAGMENT]);
if (llvmpipe->dirty & LP_NEW_TEXTURE)
lp_setup_set_sampler_textures(llvmpipe->setup,
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index a8f4a4ed463..4b51d6b964f 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -998,23 +998,22 @@ llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
void
llvmpipe_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *constants)
+ struct pipe_buffer *constants)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
- struct pipe_buffer *buffer = constants ? constants->buffer : NULL;
- unsigned size = buffer ? buffer->size : 0;
- const void *data = buffer ? llvmpipe_buffer(buffer)->data : NULL;
+ unsigned size = constants ? constants->size : 0;
+ const void *data = constants ? llvmpipe_buffer(constants)->data : NULL;
assert(shader < PIPE_SHADER_TYPES);
assert(index == 0);
- if(llvmpipe->constants[shader].buffer == buffer)
+ if(llvmpipe->constants[shader] == constants)
return;
draw_flush(llvmpipe->draw);
/* note: reference counting */
- pipe_buffer_reference(&llvmpipe->constants[shader].buffer, buffer);
+ pipe_buffer_reference(&llvmpipe->constants[shader], constants);
if(shader == PIPE_SHADER_VERTEX) {
draw_set_mapped_constant_buffer(llvmpipe->draw, PIPE_SHADER_VERTEX,
diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c
index 29fff91981a..6c29e8d8ace 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_blend.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c
@@ -462,7 +462,7 @@ compute_blend_ref(const struct pipe_blend_state *blend,
}
-ALIGN_STACK
+PIPE_ALIGN_STACK
static boolean
test_one(unsigned verbose,
FILE *fp,
@@ -531,11 +531,11 @@ test_one(unsigned verbose,
success = TRUE;
for(i = 0; i < n && success; ++i) {
if(mode == AoS) {
- ALIGN16_ATTRIB uint8_t src[LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t dst[LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t con[LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t res[LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t ref[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t src[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t dst[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t con[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t res[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t ref[LP_NATIVE_VECTOR_WIDTH/8];
int64_t start_counter = 0;
int64_t end_counter = 0;
@@ -596,11 +596,11 @@ test_one(unsigned verbose,
if(mode == SoA) {
const unsigned stride = type.length*type.width/8;
- ALIGN16_ATTRIB uint8_t src[4*LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t dst[4*LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t con[4*LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t res[4*LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t ref[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t src[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t dst[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t con[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t res[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t ref[4*LP_NATIVE_VECTOR_WIDTH/8];
int64_t start_counter = 0;
int64_t end_counter = 0;
boolean mismatch;
diff --git a/src/gallium/drivers/llvmpipe/lp_test_conv.c b/src/gallium/drivers/llvmpipe/lp_test_conv.c
index faddfb96779..c1abee424c9 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_conv.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_conv.c
@@ -142,7 +142,7 @@ add_conv_test(LLVMModuleRef module,
}
-ALIGN_STACK
+PIPE_ALIGN_STACK
static boolean
test_one(unsigned verbose,
FILE *fp,
@@ -230,8 +230,8 @@ test_one(unsigned verbose,
for(i = 0; i < n && success; ++i) {
unsigned src_stride = src_type.length*src_type.width/8;
unsigned dst_stride = dst_type.length*dst_type.width/8;
- ALIGN16_ATTRIB uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
- ALIGN16_ATTRIB uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
+ PIPE_ALIGN_VAR(16) uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
+ PIPE_ALIGN_VAR(16) uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
double fref[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
uint8_t ref[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
int64_t start_counter = 0;
diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c
index 23ea9ebbe7d..2b258f1052e 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_format.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_format.c
@@ -199,7 +199,7 @@ add_store_rgba_test(LLVMModuleRef module,
}
-ALIGN_STACK
+PIPE_ALIGN_STACK
static boolean
test_format(unsigned verbose, FILE *fp, const struct pixel_test_case *test)
{
diff --git a/src/gallium/drivers/nv04/nv04_state.c b/src/gallium/drivers/nv04/nv04_state.c
index e3dc4c5bf44..b67f1e16b1c 100644
--- a/src/gallium/drivers/nv04/nv04_state.c
+++ b/src/gallium/drivers/nv04/nv04_state.c
@@ -332,7 +332,7 @@ nv04_set_clip_state(struct pipe_context *pipe,
static void
nv04_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv04_context *nv04 = nv04_context(pipe);
struct pipe_screen *pscreen = pipe->screen;
@@ -342,13 +342,13 @@ nv04_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
if (buf) {
void *mapped;
- if (buf->buffer && buf->buffer->size &&
- (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)))
+ if (buf && buf->size &&
+ (mapped = pipe_buffer_map(pscreen, buf, PIPE_BUFFER_USAGE_CPU_READ)))
{
- memcpy(nv04->constbuf[shader], mapped, buf->buffer->size);
+ memcpy(nv04->constbuf[shader], mapped, buf->size);
nv04->constbuf_nr[shader] =
- buf->buffer->size / (4 * sizeof(float));
- pipe_buffer_unmap(pscreen, buf->buffer);
+ buf->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pscreen, buf);
}
}
}
diff --git a/src/gallium/drivers/nv10/nv10_state.c b/src/gallium/drivers/nv10/nv10_state.c
index ffc6be3c401..ad7def53b12 100644
--- a/src/gallium/drivers/nv10/nv10_state.c
+++ b/src/gallium/drivers/nv10/nv10_state.c
@@ -458,7 +458,7 @@ nv10_set_clip_state(struct pipe_context *pipe,
static void
nv10_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv10_context *nv10 = nv10_context(pipe);
struct pipe_screen *pscreen = pipe->screen;
@@ -468,13 +468,13 @@ nv10_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
if (buf) {
void *mapped;
- if (buf->buffer && buf->buffer->size &&
- (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)))
+ if (buf->size &&
+ (mapped = pipe_buffer_map(pscreen, buf, PIPE_BUFFER_USAGE_CPU_READ)))
{
- memcpy(nv10->constbuf[shader], mapped, buf->buffer->size);
+ memcpy(nv10->constbuf[shader], mapped, buf->size);
nv10->constbuf_nr[shader] =
- buf->buffer->size / (4 * sizeof(float));
- pipe_buffer_unmap(pscreen, buf->buffer);
+ buf->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pscreen, buf);
}
}
}
diff --git a/src/gallium/drivers/nv20/nv20_state.c b/src/gallium/drivers/nv20/nv20_state.c
index 3a82e63423d..45697a60efd 100644
--- a/src/gallium/drivers/nv20/nv20_state.c
+++ b/src/gallium/drivers/nv20/nv20_state.c
@@ -451,7 +451,7 @@ nv20_set_clip_state(struct pipe_context *pipe,
static void
nv20_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv20_context *nv20 = nv20_context(pipe);
struct pipe_screen *pscreen = pipe->screen;
@@ -461,13 +461,13 @@ nv20_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
if (buf) {
void *mapped;
- if (buf->buffer && buf->buffer->size &&
- (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)))
+ if (buf->size &&
+ (mapped = pipe_buffer_map(pscreen, buf, PIPE_BUFFER_USAGE_CPU_READ)))
{
- memcpy(nv20->constbuf[shader], mapped, buf->buffer->size);
+ memcpy(nv20->constbuf[shader], mapped, buf->size);
nv20->constbuf_nr[shader] =
- buf->buffer->size / (4 * sizeof(float));
- pipe_buffer_unmap(pscreen, buf->buffer);
+ buf->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pscreen, buf);
}
}
}
diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nv30/nv30_fragtex.c
index 98935678911..0cc3172dcd5 100644
--- a/src/gallium/drivers/nv30/nv30_fragtex.c
+++ b/src/gallium/drivers/nv30/nv30_fragtex.c
@@ -43,7 +43,6 @@ static struct nv30_texture_format *
nv30_fragtex_format(uint pipe_format)
{
struct nv30_texture_format *tf = nv30_texture_formats;
- char fs[128];
while (tf->defined) {
if (tf->pipe == pipe_format)
@@ -65,7 +64,7 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit)
struct nouveau_bo *bo = nouveau_bo(nv30mt->buffer);
struct nv30_texture_format *tf;
struct nouveau_stateobj *so;
- uint32_t txf, txs , txp;
+ uint32_t txf, txs;
unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
tf = nv30_fragtex_format(pt->format);
@@ -97,13 +96,6 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit)
return NULL;
}
- if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
- txp = 0;
- } else {
- txp = nv30mt->level[0].pitch;
- txf |= (1<<13) /*FIXME: NV34TCL_TX_FORMAT_LINEAR ? */;
- }
-
txs = tf->swizzle;
so = so_new(1, 8, 2);
diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c
index a80dfb04880..065c927a10d 100644
--- a/src/gallium/drivers/nv30/nv30_state.c
+++ b/src/gallium/drivers/nv30/nv30_state.c
@@ -590,12 +590,12 @@ nv30_set_clip_state(struct pipe_context *pipe,
static void
nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv30_context *nv30 = nv30_context(pipe);
- nv30->constbuf[shader] = buf->buffer;
- nv30->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float));
+ nv30->constbuf[shader] = buf;
+ nv30->constbuf_nr[shader] = buf->size / (4 * sizeof(float));
if (shader == PIPE_SHADER_VERTEX) {
nv30->dirty |= NV30_NEW_VERTPROG;
diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c
index ed0ca9e02c3..7d990f7d567 100644
--- a/src/gallium/drivers/nv40/nv40_state.c
+++ b/src/gallium/drivers/nv40/nv40_state.c
@@ -605,12 +605,12 @@ nv40_set_clip_state(struct pipe_context *pipe,
static void
nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv40_context *nv40 = nv40_context(pipe);
- nv40->constbuf[shader] = buf->buffer;
- nv40->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float));
+ nv40->constbuf[shader] = buf;
+ nv40->constbuf_nr[shader] = buf->size / (4 * sizeof(float));
if (shader == PIPE_SHADER_VERTEX) {
nv40->dirty |= NV40_NEW_VERTPROG;
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c
index 5997456e4c9..22a8498c69b 100644
--- a/src/gallium/drivers/nv50/nv50_context.c
+++ b/src/gallium/drivers/nv50/nv50_context.c
@@ -67,8 +67,12 @@ nv50_destroy(struct pipe_context *pipe)
so_ref(NULL, &nv50->state.vertprog);
if (nv50->state.fragprog)
so_ref(NULL, &nv50->state.fragprog);
- if (nv50->state.programs)
- so_ref(NULL, &nv50->state.programs);
+ if (nv50->state.geomprog)
+ so_ref(NULL, &nv50->state.geomprog);
+ if (nv50->state.fp_linkage)
+ so_ref(NULL, &nv50->state.fp_linkage);
+ if (nv50->state.gp_linkage)
+ so_ref(NULL, &nv50->state.gp_linkage);
if (nv50->state.vtxfmt)
so_ref(NULL, &nv50->state.vtxfmt);
if (nv50->state.vtxbuf)
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index cbd4c3ff86d..d024be6ea95 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -45,9 +45,11 @@
#define NV50_NEW_VERTPROG_CB (1 << 9)
#define NV50_NEW_FRAGPROG (1 << 10)
#define NV50_NEW_FRAGPROG_CB (1 << 11)
-#define NV50_NEW_ARRAYS (1 << 12)
-#define NV50_NEW_SAMPLER (1 << 13)
-#define NV50_NEW_TEXTURE (1 << 14)
+#define NV50_NEW_GEOMPROG (1 << 12)
+#define NV50_NEW_GEOMPROG_CB (1 << 13)
+#define NV50_NEW_ARRAYS (1 << 14)
+#define NV50_NEW_SAMPLER (1 << 15)
+#define NV50_NEW_TEXTURE (1 << 16)
struct nv50_blend_stateobj {
struct pipe_blend_state pipe;
@@ -129,7 +131,9 @@ struct nv50_state {
unsigned miptree_nr[PIPE_SHADER_TYPES];
struct nouveau_stateobj *vertprog;
struct nouveau_stateobj *fragprog;
- struct nouveau_stateobj *programs;
+ struct nouveau_stateobj *geomprog;
+ struct nouveau_stateobj *fp_linkage;
+ struct nouveau_stateobj *gp_linkage;
struct nouveau_stateobj *vtxfmt;
struct nouveau_stateobj *vtxbuf;
struct nouveau_stateobj *vtxattr;
@@ -157,6 +161,7 @@ struct nv50_context {
struct pipe_framebuffer_state framebuffer;
struct nv50_program *vertprog;
struct nv50_program *fragprog;
+ struct nv50_program *geomprog;
struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
unsigned vtxbuf_nr;
@@ -207,7 +212,9 @@ extern void nv50_clear(struct pipe_context *pipe, unsigned buffers,
/* nv50_program.c */
extern void nv50_vertprog_validate(struct nv50_context *nv50);
extern void nv50_fragprog_validate(struct nv50_context *nv50);
-extern void nv50_linkage_validate(struct nv50_context *nv50);
+extern void nv50_geomprog_validate(struct nv50_context *nv50);
+extern void nv50_fp_linkage_validate(struct nv50_context *nv50);
+extern void nv50_gp_linkage_validate(struct nv50_context *nv50);
extern void nv50_program_destroy(struct nv50_context *nv50,
struct nv50_program *p);
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
index 3f1edf0a139..dc8364ced7e 100644
--- a/src/gallium/drivers/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -92,12 +92,23 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
case PIPE_FORMAT_Z24S8_UNORM:
tile_flags = 0x1800;
break;
+ case PIPE_FORMAT_Z16_UNORM:
+ tile_flags = 0x6c00;
+ break;
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8Z24_UNORM:
tile_flags = 0x2800;
break;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ tile_flags = 0x7400;
+ break;
default:
- tile_flags = 0x7000;
+ if ((pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) &&
+ util_format_get_blocksizebits(pt->format) == 32)
+ tile_flags = 0x7a00;
+ else
+ tile_flags = 0x7000;
break;
}
@@ -145,7 +156,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
mt->level[0].tile_mode, tile_flags,
&mt->base.bo);
if (ret) {
- for (l = 0; l < pt->last_level; ++l)
+ for (l = 0; l <= pt->last_level; ++l)
FREE(mt->level[l].image_offset);
FREE(mt);
return NULL;
@@ -188,7 +199,7 @@ nv50_miptree_destroy(struct pipe_texture *pt)
struct nv50_miptree *mt = nv50_miptree(pt);
unsigned l;
- for (l = 0; l < pt->last_level; ++l)
+ for (l = 0; l <= pt->last_level; ++l)
FREE(mt->level[l].image_offset);
nouveau_bo_ref(NULL, &mt->base.bo);
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index 53f9f0adf31..acd695b39bc 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -92,6 +92,9 @@ struct nv50_reg {
int rhw; /* result hw for FP outputs, or interpolant index */
int acc; /* instruction where this reg is last read (first insn == 1) */
+
+ int vtx; /* vertex index, for GP inputs (TGSI Dimension.Index) */
+ int indirect[2]; /* index into pc->addr, or -1 */
};
#define NV50_MOD_NEG 1
@@ -135,9 +138,11 @@ struct nv50_pc {
int immd_nr;
struct nv50_reg **addr;
int addr_nr;
- uint8_t addr_alloc; /* set bit indicates used for TGSI_FILE_ADDRESS */
+ struct nv50_reg *sysval;
+ int sysval_nr;
struct nv50_reg *temp_temp[16];
+ struct nv50_program_exec *temp_temp_exec[16];
unsigned temp_temp_nr;
/* broadcast and destination replacement regs */
@@ -170,6 +175,8 @@ struct nv50_pc {
uint8_t edgeflag_out;
};
+static struct nv50_reg *get_address_reg(struct nv50_pc *, struct nv50_reg *);
+
static INLINE void
ctor_reg(struct nv50_reg *reg, unsigned type, int index, int hw)
{
@@ -178,7 +185,9 @@ ctor_reg(struct nv50_reg *reg, unsigned type, int index, int hw)
reg->hw = hw;
reg->mod = 0;
reg->rhw = -1;
+ reg->vtx = -1;
reg->acc = 0;
+ reg->indirect[0] = reg->indirect[1] = -1;
}
static INLINE unsigned
@@ -196,7 +205,8 @@ terminate_mbb(struct nv50_pc *pc)
/* remove records of temporary address register values */
for (i = 0; i < NV50_SU_MAX_ADDR; ++i)
- pc->r_addr[i].rhw = -1;
+ if (pc->r_addr[i].index < 0)
+ pc->r_addr[i].acc = 0;
}
static void
@@ -245,7 +255,8 @@ alloc_reg(struct nv50_pc *pc, struct nv50_reg *reg)
}
}
- assert(0);
+ NOUVEAU_ERR("out of registers\n");
+ abort();
}
static INLINE struct nv50_reg *
@@ -258,6 +269,7 @@ reg_instance(struct nv50_pc *pc, struct nv50_reg *reg)
if (reg) {
alloc_reg(pc, reg);
*ri = *reg;
+ reg->indirect[0] = reg->indirect[1] = -1;
reg->mod = 0;
}
return ri;
@@ -285,7 +297,8 @@ alloc_temp(struct nv50_pc *pc, struct nv50_reg *dst)
}
}
- assert(0);
+ NOUVEAU_ERR("out of registers\n");
+ abort();
return NULL;
}
@@ -347,23 +360,29 @@ free_temp4(struct nv50_pc *pc, struct nv50_reg *reg[4])
}
static struct nv50_reg *
-temp_temp(struct nv50_pc *pc)
+temp_temp(struct nv50_pc *pc, struct nv50_program_exec *e)
{
if (pc->temp_temp_nr >= 16)
assert(0);
pc->temp_temp[pc->temp_temp_nr] = alloc_temp(pc, NULL);
+ pc->temp_temp_exec[pc->temp_temp_nr] = e;
return pc->temp_temp[pc->temp_temp_nr++];
}
+/* This *must* be called for all nv50_program_exec that have been
+ * given as argument to temp_temp, or the temps will be leaked !
+ */
static void
-kill_temp_temp(struct nv50_pc *pc)
+kill_temp_temp(struct nv50_pc *pc, struct nv50_program_exec *e)
{
int i;
for (i = 0; i < pc->temp_temp_nr; i++)
- free_temp(pc, pc->temp_temp[i]);
- pc->temp_temp_nr = 0;
+ if (pc->temp_temp_exec[i] == e)
+ free_temp(pc, pc->temp_temp[i]);
+ if (!e)
+ pc->temp_temp_nr = 0;
}
static int
@@ -425,6 +444,8 @@ emit(struct nv50_pc *pc, struct nv50_program_exec *e)
p->exec_head = e;
p->exec_tail = e;
p->exec_size += (e->inst[0] & 1) ? 2 : 1;
+
+ kill_temp_temp(pc, e);
}
static INLINE void set_long(struct nv50_pc *, struct nv50_program_exec *);
@@ -514,11 +535,33 @@ set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e)
static INLINE void
set_addr(struct nv50_program_exec *e, struct nv50_reg *a)
{
+ assert(a->type == P_ADDR);
+
assert(!(e->inst[0] & 0x0c000000));
assert(!(e->inst[1] & 0x00000004));
e->inst[0] |= (a->hw & 3) << 26;
- e->inst[1] |= (a->hw >> 2) << 2;
+ e->inst[1] |= a->hw & 4;
+}
+
+static void
+emit_arl(struct nv50_pc *, struct nv50_reg *, struct nv50_reg *, uint8_t);
+
+static void
+emit_shl_imm(struct nv50_pc *, struct nv50_reg *, struct nv50_reg *, int);
+
+static void
+emit_mov_from_addr(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *src)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[1] = 0x40000000;
+ set_long(pc, e);
+ set_dst(pc, dst, e);
+ set_addr(e, src);
+
+ emit(pc, e);
}
static void
@@ -537,72 +580,6 @@ emit_add_addr_imm(struct nv50_pc *pc, struct nv50_reg *dst,
emit(pc, e);
}
-static struct nv50_reg *
-alloc_addr(struct nv50_pc *pc, struct nv50_reg *ref)
-{
- struct nv50_reg *a_tgsi = NULL, *a = NULL;
- int i;
- uint8_t avail = ~pc->addr_alloc;
-
- if (!ref) {
- /* allocate for TGSI_FILE_ADDRESS */
- while (avail) {
- i = ffs(avail) - 1;
-
- if (pc->r_addr[i].rhw < 0 ||
- pc->r_addr[i].acc != pc->insn_cur) {
- pc->addr_alloc |= (1 << i);
-
- pc->r_addr[i].rhw = -1;
- pc->r_addr[i].index = i;
- return &pc->r_addr[i];
- }
- avail &= ~(1 << i);
- }
- assert(0);
- return NULL;
- }
-
- /* Allocate and set an address reg so we can access 'ref'.
- *
- * If and r_addr->index will be -1 or the hw index the value
- * value in rhw is relative to. If rhw < 0, the reg has not
- * been initialized or is in use for TGSI_FILE_ADDRESS.
- */
- while (avail) { /* only consider regs that are not TGSI */
- i = ffs(avail) - 1;
- avail &= ~(1 << i);
-
- if ((!a || a->rhw >= 0) && pc->r_addr[i].rhw < 0) {
- /* prefer an usused reg with low hw index */
- a = &pc->r_addr[i];
- continue;
- }
- if (!a && pc->r_addr[i].acc != pc->insn_cur)
- a = &pc->r_addr[i];
-
- if (ref->hw - pc->r_addr[i].rhw >= 128)
- continue;
-
- if ((ref->acc >= 0 && pc->r_addr[i].index < 0) ||
- (ref->acc < 0 && pc->r_addr[i].index == ref->index)) {
- pc->r_addr[i].acc = pc->insn_cur;
- return &pc->r_addr[i];
- }
- }
- assert(a);
-
- if (ref->acc < 0)
- a_tgsi = pc->addr[ref->index];
-
- emit_add_addr_imm(pc, a, a_tgsi, (ref->hw & ~0x7f) * 4);
-
- a->rhw = ref->hw & ~0x7f;
- a->acc = pc->insn_cur;
- a->index = a_tgsi ? ref->index : -1;
- return a;
-}
-
#define INTERP_LINEAR 0
#define INTERP_FLAT 1
#define INTERP_PERSPECTIVE 2
@@ -646,12 +623,12 @@ set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s,
e->param.shift = s;
e->param.mask = m << (s % 32);
- if (src->hw > 127)
- set_addr(e, alloc_addr(pc, src));
+ if (src->hw < 0 || src->hw > 127) /* need (additional) address reg */
+ set_addr(e, get_address_reg(pc, src));
else
if (src->acc < 0) {
assert(src->type == P_CONST);
- set_addr(e, pc->addr[src->index]);
+ set_addr(e, pc->addr[src->indirect[0]]);
}
e->inst[1] |= (((src->type == P_IMMD) ? 0 : 1) << 22);
@@ -683,6 +660,12 @@ emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
if (src->type == P_ATTR) {
set_long(pc, e);
e->inst[1] |= 0x00200000;
+
+ if (src->vtx >= 0) {
+ /* indirect (vertex base + c) load from p[] */
+ e->inst[0] |= 0x01800000;
+ set_addr(e, get_address_reg(pc, src));
+ }
}
alloc_reg(pc, src);
@@ -780,7 +763,7 @@ set_src_0_restricted(struct nv50_pc *pc, struct nv50_reg *src,
struct nv50_reg *temp;
if (src->type != P_TEMP) {
- temp = temp_temp(pc);
+ temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
}
@@ -797,9 +780,14 @@ set_src_0(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
if (src->type == P_ATTR) {
set_long(pc, e);
e->inst[1] |= 0x00200000;
+
+ if (src->vtx >= 0) {
+ e->inst[0] |= 0x01800000; /* src from p[] */
+ set_addr(e, get_address_reg(pc, src));
+ }
} else
if (src->type == P_CONST || src->type == P_IMMD) {
- struct nv50_reg *temp = temp_temp(pc);
+ struct nv50_reg *temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
@@ -815,19 +803,19 @@ static void
set_src_1(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
{
if (src->type == P_ATTR) {
- struct nv50_reg *temp = temp_temp(pc);
+ struct nv50_reg *temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
} else
if (src->type == P_CONST || src->type == P_IMMD) {
- assert(!(e->inst[0] & 0x00800000));
- if (e->inst[0] & 0x01000000) {
- struct nv50_reg *temp = temp_temp(pc);
+ if (e->inst[0] & 0x01800000) {
+ struct nv50_reg *temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
} else {
+ assert(!(e->inst[0] & 0x00800000));
set_data(pc, src, 0x7f, 16, e);
e->inst[0] |= 0x00800000;
}
@@ -845,19 +833,19 @@ set_src_2(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
set_long(pc, e);
if (src->type == P_ATTR) {
- struct nv50_reg *temp = temp_temp(pc);
+ struct nv50_reg *temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
} else
if (src->type == P_CONST || src->type == P_IMMD) {
- assert(!(e->inst[0] & 0x01000000));
- if (e->inst[0] & 0x00800000) {
- struct nv50_reg *temp = temp_temp(pc);
+ if (e->inst[0] & 0x01800000) {
+ struct nv50_reg *temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
} else {
+ assert(!(e->inst[0] & 0x01000000));
set_data(pc, src, 0x7f, 32+14, e);
e->inst[0] |= 0x01000000;
}
@@ -868,6 +856,26 @@ set_src_2(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
}
static void
+set_half_src(struct nv50_pc *pc, struct nv50_reg *src, int lh,
+ struct nv50_program_exec *e, int pos)
+{
+ struct nv50_reg *r = src;
+
+ alloc_reg(pc, r);
+ if (r->type != P_TEMP) {
+ r = temp_temp(pc, e);
+ emit_mov(pc, r, src);
+ }
+
+ if (r->hw > (NV50_SU_MAX_TEMP / 2)) {
+ NOUVEAU_ERR("out of low GPRs\n");
+ abort();
+ }
+
+ e->inst[pos / 32] |= ((src->hw * 2) + lh) << (pos % 32);
+}
+
+static void
emit_mov_from_pred(struct nv50_pc *pc, struct nv50_reg *dst, int pred)
{
struct nv50_program_exec *e = exec(pc);
@@ -966,11 +974,125 @@ emit_arl(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src,
e->inst[0] |= dst->hw << 2;
e->inst[0] |= s << 16; /* shift left */
- set_src_0_restricted(pc, src, e);
+ set_src_0(pc, src, e);
emit(pc, e);
}
+static boolean
+address_reg_suitable(struct nv50_reg *a, struct nv50_reg *r)
+{
+ if (!r)
+ return FALSE;
+
+ if (r->vtx != a->vtx)
+ return FALSE;
+ if (r->vtx >= 0)
+ return (r->indirect[1] == a->indirect[1]);
+
+ if (r->hw < a->rhw || (r->hw - a->rhw) >= 128)
+ return FALSE;
+
+ if (a->index >= 0)
+ return (a->index == r->indirect[0]);
+ return (a->indirect[0] == r->indirect[0]);
+}
+
+static void
+load_vertex_base(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *a, int shift)
+{
+ struct nv50_reg mem, *temp;
+
+ ctor_reg(&mem, P_ATTR, -1, dst->vtx);
+
+ assert(dst->type == P_ADDR);
+ if (!a) {
+ emit_arl(pc, dst, &mem, 0);
+ return;
+ }
+ temp = alloc_temp(pc, NULL);
+
+ if (shift) {
+ emit_mov_from_addr(pc, temp, a);
+ if (shift < 0)
+ emit_shl_imm(pc, temp, temp, shift);
+ emit_arl(pc, dst, temp, MAX2(shift, 0));
+ }
+ emit_mov(pc, temp, &mem);
+ set_addr(pc->p->exec_tail, dst);
+
+ emit_arl(pc, dst, temp, 0);
+ free_temp(pc, temp);
+}
+
+/* case (ref == NULL): allocate address register for TGSI_FILE_ADDRESS
+ * case (vtx >= 0, acc >= 0): load vertex base from a[vtx * 4] to $aX
+ * case (vtx >= 0, acc < 0): load vertex base from s[$aY + vtx * 4] to $aX
+ * case (vtx < 0, acc >= 0): memory address too high to encode
+ * case (vtx < 0, acc < 0): get source register for TGSI_FILE_ADDRESS
+ */
+static struct nv50_reg *
+get_address_reg(struct nv50_pc *pc, struct nv50_reg *ref)
+{
+ int i;
+ struct nv50_reg *a_ref, *a = NULL;
+
+ for (i = 0; i < NV50_SU_MAX_ADDR; ++i) {
+ if (pc->r_addr[i].acc == 0)
+ a = &pc->r_addr[i]; /* an unused address reg */
+ else
+ if (address_reg_suitable(&pc->r_addr[i], ref)) {
+ pc->r_addr[i].acc = pc->insn_cur;
+ return &pc->r_addr[i];
+ } else
+ if (!a && pc->r_addr[i].index < 0 &&
+ pc->r_addr[i].acc < pc->insn_cur)
+ a = &pc->r_addr[i];
+ }
+ if (!a) {
+ /* We'll be able to spill address regs when this
+ * mess is replaced with a proper compiler ...
+ */
+ NOUVEAU_ERR("out of address regs\n");
+ abort();
+ return NULL;
+ }
+
+ /* initialize and reserve for this TGSI instruction */
+ a->rhw = 0;
+ a->index = a->indirect[0] = a->indirect[1] = -1;
+ a->acc = pc->insn_cur;
+
+ if (!ref) {
+ a->vtx = -1;
+ return a;
+ }
+ a->vtx = ref->vtx;
+
+ /* now put in the correct value ... */
+
+ if (ref->vtx >= 0) {
+ a->indirect[1] = ref->indirect[1];
+
+ /* For an indirect vertex index, we need to shift address right
+ * by 2, the address register will contain vtx * 16, we need to
+ * load from a[vtx * 4].
+ */
+ load_vertex_base(pc, a, (ref->acc < 0) ?
+ pc->addr[ref->indirect[1]] : NULL, -2);
+ } else {
+ assert(ref->acc < 0 || ref->indirect[0] < 0);
+
+ a->rhw = ref->hw & ~0x7f;
+ a->indirect[0] = ref->indirect[0];
+ a_ref = (ref->acc < 0) ? pc->addr[ref->indirect[0]] : NULL;
+
+ emit_add_addr_imm(pc, a, a_ref, a->rhw * 4);
+ }
+ return a;
+}
+
#define NV50_MAX_F32 0x880
#define NV50_MAX_S32 0x08c
#define NV50_MAX_U32 0x084
@@ -1050,6 +1172,20 @@ emit_bitop2(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
}
static void
+emit_not(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] = 0xd0000000;
+ e->inst[1] = 0x0402c000;
+ set_long(pc, e);
+ set_dst(pc, dst, e);
+ set_src_1(pc, src, e);
+
+ emit(pc, e);
+}
+
+static void
emit_shift(struct nv50_pc *pc, struct nv50_reg *dst,
struct nv50_reg *src0, struct nv50_reg *src1, unsigned dir)
{
@@ -1078,6 +1214,27 @@ emit_shift(struct nv50_pc *pc, struct nv50_reg *dst,
}
static void
+emit_shl_imm(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *src, int s)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] = 0x30000000;
+ e->inst[1] = 0xc4100000;
+ if (s < 0) {
+ e->inst[1] |= 1 << 29;
+ s = -s;
+ }
+ e->inst[1] |= ((s & 0x7f) << 16);
+
+ set_long(pc, e);
+ set_dst(pc, dst, e);
+ set_src_0(pc, src, e);
+
+ emit(pc, e);
+}
+
+static void
emit_mad(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
struct nv50_reg *src1, struct nv50_reg *src2)
{
@@ -1321,7 +1478,7 @@ emit_add_b32(struct nv50_pc *pc, struct nv50_reg *dst,
src1 = rsrc1;
if (src0->mod & rsrc1->mod & NV50_MOD_NEG) {
- src1 = alloc_temp(pc, NULL);
+ src1 = temp_temp(pc, e);
emit_cvt(pc, src1, rsrc1, -1, CVT_S32_S32);
}
@@ -1350,9 +1507,43 @@ emit_add_b32(struct nv50_pc *pc, struct nv50_reg *dst,
e->inst[0] |= 1 << 22;
emit(pc, e);
+}
+
+static void
+emit_mad_u16(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *src0, int lh_0, struct nv50_reg *src1, int lh_1,
+ struct nv50_reg *src2)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] = 0x60000000;
+ if (!pc->allow32)
+ set_long(pc, e);
+ set_dst(pc, dst, e);
+
+ set_half_src(pc, src0, lh_0, e, 9);
+ set_half_src(pc, src1, lh_1, e, 16);
+ alloc_reg(pc, src2);
+ if (is_long(e) || (src2->type != P_TEMP) || (src2->hw != dst->hw))
+ set_src_2(pc, src2, e);
+
+ emit(pc, e);
+}
+
+static void
+emit_mul_u16(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *src0, int lh_0, struct nv50_reg *src1, int lh_1)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] = 0x40000000;
+ set_long(pc, e);
+ set_dst(pc, dst, e);
+
+ set_half_src(pc, src0, lh_0, e, 9);
+ set_half_src(pc, src1, lh_1, e, 16);
- if (src1 != rsrc1)
- free_temp(pc, src1);
+ emit(pc, e);
}
static void
@@ -1362,6 +1553,9 @@ emit_sad(struct nv50_pc *pc, struct nv50_reg *dst,
struct nv50_program_exec *e = exec(pc);
e->inst[0] = 0x50000000;
+ if (!pc->allow32)
+ set_long(pc, e);
+ check_swap_src_0_1(pc, &src0, &src1);
set_dst(pc, dst, e);
set_src_0(pc, src0, e);
set_src_1(pc, src1, e);
@@ -1373,6 +1567,8 @@ emit_sad(struct nv50_pc *pc, struct nv50_reg *dst,
e->inst[1] |= 0x0c << 24;
else
e->inst[0] |= 0x81 << 8;
+
+ emit(pc, e);
}
static INLINE void
@@ -1422,10 +1618,10 @@ emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask,
if (mask & (1 << 2)) {
set_pred_wr(pc, 1, 0, pc->p->exec_tail);
- tmp[1] = temp_temp(pc);
+ tmp[1] = temp_temp(pc, NULL);
emit_minmax(pc, NV50_MAX_F32, tmp[1], src[1], zero);
- tmp[3] = temp_temp(pc);
+ tmp[3] = temp_temp(pc, NULL);
emit_minmax(pc, NV50_MAX_F32, tmp[3], src[3], neg128);
emit_minmax(pc, NV50_MIN_F32, tmp[3], tmp[3], pos128);
@@ -1524,6 +1720,18 @@ emit_ret(struct nv50_pc *pc, int pred, unsigned cc)
emit_control_flow(pc, 0x3, pred, cc);
}
+static void
+emit_prim_cmd(struct nv50_pc *pc, unsigned cmd)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] = 0xf0000000 | (cmd << 9);
+ e->inst[1] = 0xc0000000;
+ set_long(pc, e);
+
+ emit(pc, e);
+}
+
#define QOP_ADD 0
#define QOP_SUBR 1
#define QOP_SUB 2
@@ -1884,7 +2092,11 @@ convert_to_long(struct nv50_pc *pc, struct nv50_program_exec *e)
case 0x5:
/* SAD */
m = ~(0x81 << 8);
- q = 0x0c << 24;
+ q = (0x0c << 24) | ((e->inst[0] & (0x7f << 2)) << 12);
+ break;
+ case 0x6:
+ /* MAD u16 */
+ q = (e->inst[0] & (0x7f << 2)) << 12;
break;
case 0x8:
/* INTERP (move centroid, perspective and flat bits) */
@@ -1964,8 +2176,11 @@ get_supported_mods(const struct tgsi_full_instruction *insn, int i)
case TGSI_OPCODE_IMAX:
case TGSI_OPCODE_IMIN:
case TGSI_OPCODE_ISHR:
+ case TGSI_OPCODE_NOT:
+ case TGSI_OPCODE_UMAD:
case TGSI_OPCODE_UMAX:
case TGSI_OPCODE_UMIN:
+ case TGSI_OPCODE_UMUL:
case TGSI_OPCODE_USHR:
return NV50_MOD_I32;
default:
@@ -2059,14 +2274,19 @@ tgsi_dst(struct nv50_pc *pc, int c, const struct tgsi_full_dst_register *dst)
{
struct nv50_reg *r = pc->addr[dst->Register.Index * 4 + c];
if (!r) {
- r = alloc_addr(pc, NULL);
- pc->addr[dst->Register.Index * 4 + c] = r;
+ r = get_address_reg(pc, NULL);
+ r->index = dst->Register.Index * 4 + c;
+ pc->addr[r->index] = r;
}
assert(r);
return r;
}
case TGSI_FILE_NULL:
return NULL;
+ case TGSI_FILE_SYSTEM_VALUE:
+ assert(pc->sysval[dst->Register.Index].type == P_RESULT);
+ assert(c == 0);
+ return &pc->sysval[dst->Register.Index];
default:
break;
}
@@ -2096,6 +2316,18 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
switch (src->Register.File) {
case TGSI_FILE_INPUT:
r = &pc->attr[src->Register.Index * 4 + c];
+
+ if (!src->Dimension.Dimension)
+ break;
+ r = reg_instance(pc, r);
+ r->vtx = src->Dimension.Index;
+
+ if (!src->Dimension.Indirect)
+ break;
+ swz = tgsi_util_get_src_register_swizzle(
+ &src->DimIndirect, 0);
+ r->acc = -1;
+ r->indirect[1] = src->DimIndirect.Index * 4 + swz;
break;
case TGSI_FILE_TEMPORARY:
r = &pc->temp[src->Register.Index * 4 + c];
@@ -2109,12 +2341,12 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
* use the index field to select the address reg.
*/
r = reg_instance(pc, NULL);
+ ctor_reg(r, P_CONST, -1, src->Register.Index * 4 + c);
+
swz = tgsi_util_get_src_register_swizzle(
- &src->Indirect, 0);
- ctor_reg(r, P_CONST,
- src->Indirect.Index * 4 + swz,
- src->Register.Index * 4 + c);
+ &src->Indirect, 0);
r->acc = -1;
+ r->indirect[0] = src->Indirect.Index * 4 + swz;
break;
case TGSI_FILE_IMMEDIATE:
r = &pc->immd[src->Register.Index * 4 + c];
@@ -2125,6 +2357,10 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
r = pc->addr[src->Register.Index * 4 + c];
assert(r);
break;
+ case TGSI_FILE_SYSTEM_VALUE:
+ assert(c == 0);
+ r = &pc->sysval[src->Register.Index];
+ break;
default:
assert(0);
break;
@@ -2153,7 +2389,7 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
}
if ((r->mod & mod) != r->mod) {
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
emit_cvt(pc, temp, r, -1, cvn);
r->mod = 0;
r = temp;
@@ -2161,7 +2397,7 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
r->mod |= mod & NV50_MOD_I32;
assert(r);
- if (r->acc >= 0 && r != temp)
+ if (r->acc >= 0 && r->vtx < 0 && r != temp)
return reg_instance(pc, r); /* will clear r->mod */
return r;
}
@@ -2341,7 +2577,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
brdc = temp = pc->r_brdc;
if (brdc && brdc->type != P_TEMP) {
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
if (sat)
brdc = temp;
} else
@@ -2350,7 +2586,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
if (!(mask & (1 << c)) || dst[c]->type == P_TEMP)
continue;
/* rdst[c] = dst[c]; */ /* done above */
- dst[c] = temp_temp(pc);
+ dst[c] = temp_temp(pc, NULL);
}
}
@@ -2383,10 +2619,14 @@ nv50_program_tx_insn(struct nv50_pc *pc,
}
break;
case TGSI_OPCODE_ARL:
- assert(src[0][0]);
- temp = temp_temp(pc);
- emit_cvt(pc, temp, src[0][0], -1, CVT_FLOOR | CVT_S32_F32);
- emit_arl(pc, dst[0], temp, 4);
+ temp = temp_temp(pc, NULL);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_cvt(pc, temp, src[0][c], -1,
+ CVT_FLOOR | CVT_S32_F32);
+ emit_arl(pc, dst[c], temp, 4);
+ }
break;
case TGSI_OPCODE_BGNLOOP:
pc->loop_brka[pc->loop_lvl] = emit_breakaddr(pc);
@@ -2441,7 +2681,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
if (!(mask &= 7))
break;
if (temp == dst[3])
- temp = brdc = temp_temp(pc);
+ temp = brdc = temp_temp(pc, NULL);
}
emit_precossin(pc, temp, src[0][0]);
emit_flop(pc, NV50_FLOP_COS, brdc, temp);
@@ -2493,6 +2733,9 @@ nv50_program_tx_insn(struct nv50_pc *pc,
pc->if_insn[pc->if_lvl++] = pc->p->exec_tail;
terminate_mbb(pc);
break;
+ case TGSI_OPCODE_EMIT:
+ emit_prim_cmd(pc, 1);
+ break;
case TGSI_OPCODE_ENDIF:
pc->if_insn[--pc->if_lvl]->param.index = pc->p->exec_size;
@@ -2516,8 +2759,12 @@ nv50_program_tx_insn(struct nv50_pc *pc,
pc->loop_brka[pc->loop_lvl]->param.index = pc->p->exec_size;
terminate_mbb(pc);
break;
+ case TGSI_OPCODE_ENDPRIM:
+ emit_prim_cmd(pc, 2);
+ break;
case TGSI_OPCODE_ENDSUB:
assert(pc->in_subroutine);
+ terminate_mbb(pc);
pc->in_subroutine = FALSE;
break;
case TGSI_OPCODE_EX2:
@@ -2529,8 +2776,8 @@ nv50_program_tx_insn(struct nv50_pc *pc,
struct nv50_reg *t[2];
assert(!temp);
- t[0] = temp_temp(pc);
- t[1] = temp_temp(pc);
+ t[0] = temp_temp(pc, NULL);
+ t[1] = temp_temp(pc, NULL);
if (mask & 0x6)
emit_mov(pc, t[0], src[0][0]);
@@ -2575,7 +2822,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
}
break;
case TGSI_OPCODE_FRC:
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
for (c = 0; c < 4; c++) {
if (!(mask & (1 << c)))
continue;
@@ -2639,9 +2886,9 @@ nv50_program_tx_insn(struct nv50_pc *pc,
{
struct nv50_reg *t[2];
- t[0] = temp_temp(pc);
+ t[0] = temp_temp(pc, NULL);
if (mask & (1 << 1))
- t[1] = temp_temp(pc);
+ t[1] = temp_temp(pc, NULL);
else
t[1] = t[0];
@@ -2664,7 +2911,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
}
break;
case TGSI_OPCODE_LRP:
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
for (c = 0; c < 4; c++) {
if (!(mask & (1 << c)))
continue;
@@ -2707,10 +2954,19 @@ nv50_program_tx_insn(struct nv50_pc *pc,
emit_mul(pc, dst[c], src[0][c], src[1][c]);
}
break;
+ case TGSI_OPCODE_NOT:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_not(pc, dst[c], src[0][c]);
+ }
+ break;
case TGSI_OPCODE_POW:
emit_pow(pc, brdc, src[0][0], src[1][0]);
break;
case TGSI_OPCODE_RCP:
+ if (!sat && popcnt4(mask) == 1)
+ brdc = dst[ffs(mask) - 1];
emit_flop(pc, NV50_FLOP_RCP, brdc, src[0][0]);
break;
case TGSI_OPCODE_RET:
@@ -2719,6 +2975,8 @@ nv50_program_tx_insn(struct nv50_pc *pc,
emit_ret(pc, -1, 0);
break;
case TGSI_OPCODE_RSQ:
+ if (!sat && popcnt4(mask) == 1)
+ brdc = dst[ffs(mask) - 1];
src[0][0]->mod |= NV50_MOD_ABS;
emit_flop(pc, NV50_FLOP_RSQ, brdc, src[0][0]);
break;
@@ -2730,7 +2988,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
}
break;
case TGSI_OPCODE_SCS:
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
if (mask & 3)
emit_precossin(pc, temp, src[0][0]);
if (mask & (1 << 0))
@@ -2759,7 +3017,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
if (!(mask &= 7))
break;
if (temp == dst[3])
- temp = brdc = temp_temp(pc);
+ temp = brdc = temp_temp(pc, NULL);
}
emit_precossin(pc, temp, src[0][0]);
emit_flop(pc, NV50_FLOP_SIN, brdc, temp);
@@ -2847,8 +3105,41 @@ nv50_program_tx_insn(struct nv50_pc *pc,
emit_minmax(pc, 0x0a4, dst[c], src[0][c], src[1][c]);
}
break;
+ case TGSI_OPCODE_UMAD:
+ {
+ assert(!temp);
+ temp = temp_temp(pc, NULL);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mul_u16(pc, temp, src[0][c], 0, src[1][c], 1);
+ emit_mad_u16(pc, temp, src[0][c], 1, src[1][c], 0,
+ temp);
+ emit_shl_imm(pc, temp, temp, 16);
+ emit_mad_u16(pc, temp, src[0][c], 0, src[1][c], 0,
+ temp);
+ emit_add_b32(pc, dst[c], temp, src[2][c]);
+ }
+ }
+ break;
+ case TGSI_OPCODE_UMUL:
+ {
+ assert(!temp);
+ temp = temp_temp(pc, NULL);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mul_u16(pc, temp, src[0][c], 0, src[1][c], 1);
+ emit_mad_u16(pc, temp, src[0][c], 1, src[1][c], 0,
+ temp);
+ emit_shl_imm(pc, temp, temp, 16);
+ emit_mad_u16(pc, dst[c], src[0][c], 0, src[1][c], 0,
+ temp);
+ }
+ }
+ break;
case TGSI_OPCODE_XPD:
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
if (mask & (1 << 0)) {
emit_mul(pc, temp, src[0][2], src[1][1]);
emit_msb(pc, dst[0], src[0][1], src[1][2], temp);
@@ -2876,6 +3167,8 @@ nv50_program_tx_insn(struct nv50_pc *pc,
emit_nop(pc);
pc->p->exec_tail->inst[1] |= 1; /* set exit bit */
+
+ terminate_mbb(pc);
break;
default:
NOUVEAU_ERR("invalid opcode %d\n", inst->Instruction.Opcode);
@@ -2902,7 +3195,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
}
}
- kill_temp_temp(pc);
+ kill_temp_temp(pc, NULL);
pc->reg_instance_nr = 0;
return TRUE;
@@ -3101,7 +3394,7 @@ nv50_tgsi_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
if (is_scalar_op(insn.Instruction.Opcode)) {
pc->r_brdc = tgsi_broadcast_dst(pc, fd, deqs);
if (!pc->r_brdc)
- pc->r_brdc = temp_temp(pc);
+ pc->r_brdc = temp_temp(pc, NULL);
return nv50_program_tx_insn(pc, &insn);
}
pc->r_brdc = NULL;
@@ -3171,17 +3464,40 @@ load_interpolant(struct nv50_pc *pc, struct nv50_reg *reg)
* value of 0 for back-facing, and 0xffffffff for front-facing.
*/
static void
-load_frontfacing(struct nv50_pc *pc, struct nv50_reg *a)
+load_frontfacing(struct nv50_pc *pc, struct nv50_reg *sv)
{
- struct nv50_reg *one = alloc_immd(pc, 1.0f);
+ struct nv50_reg *temp = alloc_temp(pc, NULL);
+ int r_pred = 0;
- assert(a->rhw == -1);
- alloc_reg(pc, a); /* do this before rhw is set */
- a->rhw = 255;
- load_interpolant(pc, a);
- emit_bitop2(pc, a, a, one, TGSI_OPCODE_AND);
+ temp->rhw = 255;
+ emit_interp(pc, temp, NULL, INTERP_FLAT);
- FREE(one);
+ emit_cvt(pc, sv, temp, r_pred, CVT_ABS | CVT_F32_S32);
+
+ emit_not(pc, temp, temp);
+ set_pred(pc, 0x2, r_pred, pc->p->exec_tail);
+ emit_cvt(pc, sv, temp, -1, CVT_F32_S32);
+ set_pred(pc, 0x2, r_pred, pc->p->exec_tail);
+
+ free_temp(pc, temp);
+}
+
+static void
+copy_semantic_info(struct nv50_program *p)
+{
+ unsigned i, id;
+
+ for (i = 0; i < p->cfg.in_nr; ++i) {
+ id = p->cfg.in[i].id;
+ p->cfg.in[i].sn = p->info.input_semantic_name[id];
+ p->cfg.in[i].si = p->info.input_semantic_index[id];
+ }
+
+ for (i = 0; i < p->cfg.out_nr; ++i) {
+ id = p->cfg.out[i].id;
+ p->cfg.out[i].sn = p->info.output_semantic_name[id];
+ p->cfg.out[i].si = p->info.output_semantic_index[id];
+ }
}
static boolean
@@ -3190,7 +3506,7 @@ nv50_program_tx_prep(struct nv50_pc *pc)
struct tgsi_parse_context tp;
struct nv50_program *p = pc->p;
boolean ret = FALSE;
- unsigned i, c, flat_nr = 0;
+ unsigned i, c, instance_id, vertex_id, flat_nr = 0;
tgsi_parse_init(&tp, pc->p->pipe.tokens);
while (!tgsi_parse_end_of_tokens(&tp)) {
@@ -3230,13 +3546,13 @@ nv50_program_tx_prep(struct nv50_pc *pc)
switch (d->Semantic.Name) {
case TGSI_SEMANTIC_BCOLOR:
p->cfg.two_side[si].hw = first;
- if (p->cfg.io_nr > first)
- p->cfg.io_nr = first;
+ if (p->cfg.out_nr > first)
+ p->cfg.out_nr = first;
break;
case TGSI_SEMANTIC_PSIZE:
p->cfg.psiz = first;
- if (p->cfg.io_nr > first)
- p->cfg.io_nr = first;
+ if (p->cfg.out_nr > first)
+ p->cfg.out_nr = first;
break;
case TGSI_SEMANTIC_EDGEFLAG:
pc->edgeflag_out = first;
@@ -3276,6 +3592,37 @@ nv50_program_tx_prep(struct nv50_pc *pc)
pc->interp_mode[i] = mode;
}
break;
+ case TGSI_FILE_SYSTEM_VALUE:
+ assert(d->Declaration.Semantic);
+ switch (d->Semantic.Name) {
+ case TGSI_SEMANTIC_FACE:
+ assert(p->type == PIPE_SHADER_FRAGMENT);
+ load_frontfacing(pc,
+ &pc->sysval[first]);
+ break;
+ case TGSI_SEMANTIC_INSTANCEID:
+ assert(p->type == PIPE_SHADER_VERTEX);
+ instance_id = first;
+ p->cfg.regs[0] |= (1 << 4);
+ break;
+ case TGSI_SEMANTIC_PRIMID:
+ assert(p->type != PIPE_SHADER_VERTEX);
+ p->cfg.prim_id = first;
+ break;
+ /*
+ case TGSI_SEMANTIC_PRIMIDIN:
+ assert(p->type == PIPE_SHADER_GEOMETRY);
+ pc->sysval[first].hw = 6;
+ p->cfg.regs[0] |= (1 << 8);
+ break;
+ case TGSI_SEMANTIC_VERTEXID:
+ assert(p->type == PIPE_SHADER_VERTEX);
+ vertex_id = first;
+ p->cfg.regs[0] |= (1 << 12) | (1 << 0);
+ break;
+ */
+ }
+ break;
case TGSI_FILE_ADDRESS:
case TGSI_FILE_CONSTANT:
case TGSI_FILE_SAMPLER:
@@ -3296,68 +3643,96 @@ nv50_program_tx_prep(struct nv50_pc *pc)
}
}
- if (p->type == PIPE_SHADER_VERTEX) {
+ if (p->type == PIPE_SHADER_VERTEX || p->type == PIPE_SHADER_GEOMETRY) {
int rid = 0;
- for (i = 0; i < pc->attr_nr * 4; ++i) {
- if (pc->attr[i].acc) {
- pc->attr[i].hw = rid++;
- p->cfg.attr[i / 32] |= 1 << (i % 32);
+ if (p->type == PIPE_SHADER_GEOMETRY) {
+ for (i = 0; i < pc->attr_nr; ++i) {
+ p->cfg.in[i].hw = rid;
+ p->cfg.in[i].id = i;
+
+ for (c = 0; c < 4; ++c) {
+ int n = i * 4 + c;
+ if (!pc->attr[n].acc)
+ continue;
+ pc->attr[n].hw = rid++;
+ p->cfg.in[i].mask |= 1 << c;
+ }
+ }
+ } else {
+ for (i = 0; i < pc->attr_nr * 4; ++i) {
+ if (pc->attr[i].acc) {
+ pc->attr[i].hw = rid++;
+ p->cfg.attr[i / 32] |= 1 << (i % 32);
+ }
}
+ if (p->cfg.regs[0] & (1 << 0))
+ pc->sysval[vertex_id].hw = rid++;
+ if (p->cfg.regs[0] & (1 << 4))
+ pc->sysval[instance_id].hw = rid++;
}
for (i = 0, rid = 0; i < pc->result_nr; ++i) {
- p->cfg.io[i].hw = rid;
- p->cfg.io[i].id = i;
+ p->cfg.out[i].hw = rid;
+ p->cfg.out[i].id = i;
for (c = 0; c < 4; ++c) {
int n = i * 4 + c;
if (!pc->result[n].acc)
continue;
pc->result[n].hw = rid++;
- p->cfg.io[i].mask |= 1 << c;
+ p->cfg.out[i].mask |= 1 << c;
}
}
+ if (p->cfg.prim_id < 0x40) {
+ /* GP has to write to PrimitiveID */
+ ctor_reg(&pc->sysval[p->cfg.prim_id],
+ P_RESULT, p->cfg.prim_id, rid);
+ p->cfg.prim_id = rid++;
+ }
for (c = 0; c < 2; ++c)
if (p->cfg.two_side[c].hw < 0x40)
- p->cfg.two_side[c] = p->cfg.io[
+ p->cfg.two_side[c] = p->cfg.out[
p->cfg.two_side[c].hw];
if (p->cfg.psiz < 0x40)
- p->cfg.psiz = p->cfg.io[p->cfg.psiz].hw;
+ p->cfg.psiz = p->cfg.out[p->cfg.psiz].hw;
+
+ copy_semantic_info(p);
} else
if (p->type == PIPE_SHADER_FRAGMENT) {
- int rid, aid;
+ int rid, aid, base;
unsigned n = 0, m = pc->attr_nr - flat_nr;
pc->allow32 = TRUE;
- int base = (TGSI_SEMANTIC_POSITION ==
- p->info.input_semantic_name[0]) ? 0 : 1;
+ base = (TGSI_SEMANTIC_POSITION ==
+ p->info.input_semantic_name[0]) ? 0 : 1;
/* non-flat interpolants have to be mapped to
* the lower hardware IDs, so sort them:
*/
for (i = 0; i < pc->attr_nr; i++) {
if (pc->interp_mode[i] == INTERP_FLAT)
- p->cfg.io[m++].id = i;
+ p->cfg.in[m++].id = i;
else {
if (!(pc->interp_mode[i] & INTERP_PERSPECTIVE))
- p->cfg.io[n].linear = TRUE;
- p->cfg.io[n++].id = i;
+ p->cfg.in[n].linear = TRUE;
+ p->cfg.in[n++].id = i;
}
}
+ copy_semantic_info(p);
if (!base) /* set w-coordinate mask from perspective interp */
- p->cfg.io[0].mask |= p->cfg.regs[1] >> 24;
+ 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.io[0].mask);
+ base ? (p->cfg.regs[1] >> 24) : p->cfg.in[0].mask);
for (n = 0; n < pc->attr_nr; ++n) {
- p->cfg.io[n].hw = rid = aid;
- i = p->cfg.io[n].id;
+ p->cfg.in[n].hw = rid = aid;
+ i = p->cfg.in[n].id;
if (p->info.input_semantic_name[n] ==
TGSI_SEMANTIC_FACE) {
@@ -3369,15 +3744,15 @@ nv50_program_tx_prep(struct nv50_pc *pc)
if (!pc->attr[i * 4 + c].acc)
continue;
pc->attr[i * 4 + c].rhw = rid++;
- p->cfg.io[n].mask |= 1 << c;
+ p->cfg.in[n].mask |= 1 << c;
load_interpolant(pc, &pc->attr[i * 4 + c]);
}
- aid += popcnt4(p->cfg.io[n].mask);
+ aid += popcnt4(p->cfg.in[n].mask);
}
if (!base)
- p->cfg.regs[1] |= p->cfg.io[0].mask << 24;
+ p->cfg.regs[1] |= p->cfg.in[0].mask << 24;
m = popcnt4(p->cfg.regs[1] >> 24);
@@ -3387,32 +3762,33 @@ nv50_program_tx_prep(struct nv50_pc *pc)
p->cfg.regs[1] |= aid - m;
if (flat_nr) {
- i = p->cfg.io[pc->attr_nr - flat_nr].hw;
+ i = p->cfg.in[pc->attr_nr - flat_nr].hw;
p->cfg.regs[1] |= (i - m) << 16;
} else
p->cfg.regs[1] |= p->cfg.regs[1] << 16;
/* mark color semantic for light-twoside */
- n = 0x40;
- for (i = 0; i < pc->attr_nr; i++) {
- ubyte si, sn;
-
- sn = p->info.input_semantic_name[p->cfg.io[i].id];
- si = p->info.input_semantic_index[p->cfg.io[i].id];
-
- if (sn == TGSI_SEMANTIC_COLOR) {
- p->cfg.two_side[si] = p->cfg.io[i];
-
- /* increase colour count */
- p->cfg.regs[0] += popcnt4(
- p->cfg.two_side[si].mask) << 16;
-
- n = MIN2(n, p->cfg.io[i].hw - m);
+ n = 0x80;
+ for (i = 0; i < p->cfg.in_nr; i++) {
+ if (p->cfg.in[i].sn == TGSI_SEMANTIC_COLOR) {
+ n = MIN2(n, p->cfg.in[i].hw - m);
+ p->cfg.two_side[p->cfg.in[i].si] = p->cfg.in[i];
+
+ p->cfg.regs[0] += /* increase colour count */
+ popcnt4(p->cfg.in[i].mask) << 16;
}
}
- if (n < 0x40)
+ if (n < 0x80)
p->cfg.regs[0] += n;
+ if (p->cfg.prim_id < 0x40) {
+ pc->sysval[p->cfg.prim_id].rhw = rid++;
+ emit_interp(pc, &pc->sysval[p->cfg.prim_id], NULL,
+ INTERP_FLAT);
+ /* increase FP_INTERPOLANT_CTRL_COUNT */
+ p->cfg.regs[1] += 1;
+ }
+
/* Initialize FP results:
* FragDepth is always first TGSI and last hw output
*/
@@ -3466,10 +3842,31 @@ free_nv50_pc(struct nv50_pc *pc)
FREE(pc->attr);
if (pc->temp)
FREE(pc->temp);
+ if (pc->sysval)
+ FREE(pc->sysval);
+ if (pc->insn_pos)
+ FREE(pc->insn_pos);
FREE(pc);
}
+static INLINE uint32_t
+nv50_map_gs_output_prim(unsigned pprim)
+{
+ switch (pprim) {
+ case PIPE_PRIM_POINTS:
+ return NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE_POINTS;
+ case PIPE_PRIM_LINE_STRIP:
+ return NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE_LINE_STRIP;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ return NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE_TRIANGLE_STRIP;
+ default:
+ NOUVEAU_ERR("invalid GS_OUTPUT_PRIMITIVE: %u\n", pprim);
+ abort();
+ return 0;
+ }
+}
+
static boolean
ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p)
{
@@ -3483,25 +3880,55 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p)
pc->param_nr = p->info.file_max[TGSI_FILE_CONSTANT] + 1;
pc->addr_nr = p->info.file_max[TGSI_FILE_ADDRESS] + 1;
assert(pc->addr_nr <= 2);
+ pc->sysval_nr = p->info.file_max[TGSI_FILE_SYSTEM_VALUE] + 1;
p->cfg.high_temp = 4;
p->cfg.two_side[0].hw = 0x40;
p->cfg.two_side[1].hw = 0x40;
+ p->cfg.prim_id = 0x40;
p->cfg.edgeflag_in = pc->edgeflag_out = 0xff;
+ for (i = 0; i < p->info.num_properties; ++i) {
+ unsigned *data = &p->info.properties[i].data[0];
+
+ switch (p->info.properties[i].name) {
+ case TGSI_PROPERTY_GS_OUTPUT_PRIM:
+ p->cfg.prim_type = nv50_map_gs_output_prim(data[0]);
+ break;
+ case TGSI_PROPERTY_GS_MAX_VERTICES:
+ p->cfg.vert_count = data[0];
+ break;
+ default:
+ break;
+ }
+ }
+
switch (p->type) {
case PIPE_SHADER_VERTEX:
p->cfg.psiz = 0x40;
p->cfg.clpd = 0x40;
- p->cfg.io_nr = pc->result_nr;
+ p->cfg.out_nr = pc->result_nr;
+ break;
+ case PIPE_SHADER_GEOMETRY:
+ assert(p->cfg.prim_type);
+ assert(p->cfg.vert_count);
+
+ p->cfg.psiz = 0x80;
+ p->cfg.clpd = 0x80;
+ p->cfg.prim_id = 0x80;
+ p->cfg.out_nr = pc->result_nr;
+ p->cfg.in_nr = pc->attr_nr;
+
+ p->cfg.two_side[0].hw = 0x80;
+ p->cfg.two_side[1].hw = 0x80;
break;
case PIPE_SHADER_FRAGMENT:
rtype[0] = rtype[1] = P_TEMP;
p->cfg.regs[0] = 0x01000004;
- p->cfg.io_nr = pc->attr_nr;
+ p->cfg.in_nr = pc->attr_nr;
if (p->info.writes_z) {
p->cfg.regs[2] |= 0x00000100;
@@ -3559,7 +3986,16 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p)
return FALSE;
}
for (i = 0; i < NV50_SU_MAX_ADDR; ++i)
- ctor_reg(&pc->r_addr[i], P_ADDR, -256, i + 1);
+ ctor_reg(&pc->r_addr[i], P_ADDR, -1, i + 1);
+
+ if (pc->sysval_nr) {
+ pc->sysval = CALLOC(pc->sysval_nr, sizeof(struct nv50_reg *));
+ if (!pc->sysval)
+ return FALSE;
+ /* will only ever use SYSTEM_VALUE[i].x (hopefully) */
+ for (i = 0; i < pc->sysval_nr; ++i)
+ ctor_reg(&pc->sysval[i], rtype[0], i, -1);
+ }
return TRUE;
}
@@ -3721,13 +4157,17 @@ nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p)
if (p->param_nr) {
unsigned cb;
- uint32_t *map = pipe_buffer_map(pscreen, nv50->constbuf[p->type],
+ uint32_t *map = pipe_buffer_map(pscreen,
+ nv50->constbuf[p->type],
PIPE_BUFFER_USAGE_CPU_READ);
-
- if (p->type == PIPE_SHADER_VERTEX)
+ switch (p->type) {
+ case PIPE_SHADER_GEOMETRY: cb = NV50_CB_PGP; break;
+ case PIPE_SHADER_FRAGMENT: cb = NV50_CB_PFP; break;
+ default:
cb = NV50_CB_PVP;
- else
- cb = NV50_CB_PFP;
+ assert(p->type == PIPE_SHADER_VERTEX);
+ break;
+ }
nv50_program_upload_data(nv50, map, 0, p->param_nr, cb);
pipe_buffer_unmap(pscreen, nv50->constbuf[p->type]);
@@ -3821,19 +4261,18 @@ nv50_vertprog_validate(struct nv50_context *nv50)
nv50_program_validate_data(nv50, p);
nv50_program_validate_code(nv50, p);
- so = so_new(5, 8, 2);
+ so = so_new(5, 7, 2);
so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2);
so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
- NOUVEAU_BO_HIGH, 0, 0);
+ NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
- NOUVEAU_BO_LOW, 0, 0);
+ NOUVEAU_BO_LOW, 0, 0);
so_method(so, tesla, NV50TCL_VP_ATTR_EN_0, 2);
so_data (so, p->cfg.attr[0]);
so_data (so, p->cfg.attr[1]);
so_method(so, tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
so_data (so, p->cfg.high_result);
- so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 2);
- so_data (so, p->cfg.high_result); //8);
+ so_method(so, tesla, NV50TCL_VP_REG_ALLOC_TEMP, 1);
so_data (so, p->cfg.high_temp);
so_method(so, tesla, NV50TCL_VP_START_ID, 1);
so_data (so, 0); /* program start offset */
@@ -3877,12 +4316,51 @@ nv50_fragprog_validate(struct nv50_context *nv50)
so_ref(NULL, &so);
}
-static void
+void
+nv50_geomprog_validate(struct nv50_context *nv50)
+{
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nv50_program *p = nv50->geomprog;
+ struct nouveau_stateobj *so;
+
+ if (!p->translated) {
+ nv50_program_validate(nv50, p);
+ if (!p->translated)
+ assert(0);
+ }
+
+ nv50_program_validate_data(nv50, p);
+ nv50_program_validate_code(nv50, p);
+
+ so = so_new(6, 7, 2);
+ so_method(so, tesla, NV50TCL_GP_ADDRESS_HIGH, 2);
+ so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+ NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+ NOUVEAU_BO_LOW, 0, 0);
+ so_method(so, tesla, NV50TCL_GP_REG_ALLOC_TEMP, 1);
+ so_data (so, p->cfg.high_temp);
+ so_method(so, tesla, NV50TCL_GP_REG_ALLOC_RESULT, 1);
+ so_data (so, p->cfg.high_result);
+ so_method(so, tesla, NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE, 1);
+ so_data (so, p->cfg.prim_type);
+ so_method(so, tesla, NV50TCL_GP_VERTEX_OUTPUT_COUNT, 1);
+ so_data (so, p->cfg.vert_count);
+ so_method(so, tesla, NV50TCL_GP_START_ID, 1);
+ so_data (so, 0);
+ so_ref(so, &nv50->state.geomprog);
+ so_ref(NULL, &so);
+}
+
+static uint32_t
nv50_pntc_replace(struct nv50_context *nv50, uint32_t pntc[8], unsigned base)
{
+ struct nv50_program *vp;
struct nv50_program *fp = nv50->fragprog;
- struct nv50_program *vp = nv50->vertprog;
unsigned i, c, m = base;
+ uint32_t origin = 0x00000010;
+
+ vp = nv50->geomprog ? nv50->geomprog : nv50->vertprog;
/* XXX: this might not work correctly in all cases yet - we'll
* just assume that an FP generic input that is not written in
@@ -3890,58 +4368,59 @@ nv50_pntc_replace(struct nv50_context *nv50, uint32_t pntc[8], unsigned base)
*/
memset(pntc, 0, 8 * sizeof(uint32_t));
- for (i = 0; i < fp->cfg.io_nr; i++) {
- uint8_t sn, si;
- uint8_t j, k = fp->cfg.io[i].id;
- unsigned n = popcnt4(fp->cfg.io[i].mask);
+ for (i = 0; i < fp->cfg.in_nr; i++) {
+ unsigned j, n = popcnt4(fp->cfg.in[i].mask);
- if (fp->info.input_semantic_name[k] != TGSI_SEMANTIC_GENERIC) {
+ if (fp->cfg.in[i].sn != TGSI_SEMANTIC_GENERIC) {
m += n;
continue;
}
- for (j = 0; j < vp->info.num_outputs; ++j) {
- sn = vp->info.output_semantic_name[j];
- si = vp->info.output_semantic_index[j];
-
- if (sn == fp->info.input_semantic_name[k] &&
- si == fp->info.input_semantic_index[k])
+ for (j = 0; j < vp->cfg.out_nr; ++j)
+ if (vp->cfg.out[j].sn == fp->cfg.in[i].sn &&
+ vp->cfg.out[j].si == fp->cfg.in[i].si)
break;
- }
- if (j < vp->info.num_outputs) {
- ubyte mode =
- nv50->rasterizer->pipe.sprite_coord_mode[si];
+ if (j < vp->cfg.out_nr) {
+ ubyte mode = nv50->rasterizer->pipe.sprite_coord_mode[
+ vp->cfg.out[j].si];
if (mode == PIPE_SPRITE_COORD_NONE) {
m += n;
continue;
- }
+ } else
+ if (mode == PIPE_SPRITE_COORD_LOWER_LEFT)
+ origin = 0;
}
/* this is either PointCoord or replaced by sprite coords */
for (c = 0; c < 4; c++) {
- if (!(fp->cfg.io[i].mask & (1 << c)))
+ if (!(fp->cfg.in[i].mask & (1 << c)))
continue;
pntc[m / 8] |= (c + 1) << ((m % 8) * 4);
++m;
}
}
+ return origin;
}
static int
-nv50_sreg4_map(uint32_t *p_map, int mid, uint32_t lin[4],
- struct nv50_sreg4 *fpi, struct nv50_sreg4 *vpo)
+nv50_vec4_map(uint32_t *map32, int mid, uint8_t zval, uint32_t lin[4],
+ struct nv50_sreg4 *fpi, struct nv50_sreg4 *vpo)
{
int c;
uint8_t mv = vpo->mask, mf = fpi->mask, oid = vpo->hw;
- uint8_t *map = (uint8_t *)p_map;
+ uint8_t *map = (uint8_t *)map32;
for (c = 0; c < 4; ++c) {
if (mf & 1) {
if (fpi->linear == TRUE)
lin[mid / 32] |= 1 << (mid % 32);
- map[mid++] = (mv & 1) ? oid : ((c == 3) ? 0x41 : 0x40);
+ if (mv & 1)
+ map[mid] = oid;
+ else
+ map[mid] = (c == 3) ? (zval + 1) : zval;
+ ++mid;
}
oid += mv & 1;
@@ -3953,34 +4432,42 @@ nv50_sreg4_map(uint32_t *p_map, int mid, uint32_t lin[4],
}
void
-nv50_linkage_validate(struct nv50_context *nv50)
+nv50_fp_linkage_validate(struct nv50_context *nv50)
{
struct nouveau_grobj *tesla = nv50->screen->tesla;
struct nv50_program *vp = nv50->vertprog;
struct nv50_program *fp = nv50->fragprog;
struct nouveau_stateobj *so;
- struct nv50_sreg4 dummy, *vpo;
+ struct nv50_sreg4 dummy;
int i, n, c, m = 0;
- uint32_t map[16], lin[4], reg[5], pcrd[8];
+ uint32_t map[16], lin[4], reg[6], pcrd[8];
+ uint8_t zval = 0x40;
+ if (nv50->geomprog) {
+ vp = nv50->geomprog;
+ zval = 0x80;
+ }
memset(map, 0, sizeof(map));
memset(lin, 0, sizeof(lin));
reg[1] = 0x00000004; /* low and high clip distance map ids */
reg[2] = 0x00000000; /* layer index map id (disabled, GP only) */
reg[3] = 0x00000000; /* point size map id & enable */
+ reg[5] = 0x00000000; /* primitive ID map slot */
reg[0] = fp->cfg.regs[0]; /* colour semantic reg */
reg[4] = fp->cfg.regs[1]; /* interpolant info */
dummy.linear = FALSE;
dummy.mask = 0xf; /* map all components of HPOS */
- m = nv50_sreg4_map(map, m, lin, &dummy, &vp->cfg.io[0]);
+ m = nv50_vec4_map(map, m, zval, lin, &dummy, &vp->cfg.out[0]);
dummy.mask = 0x0;
if (vp->cfg.clpd < 0x40) {
- for (c = 0; c < vp->cfg.clpd_nr; ++c)
- map[m++] = vp->cfg.clpd + c;
+ for (c = 0; c < vp->cfg.clpd_nr; ++c) {
+ map[m / 4] |= (vp->cfg.clpd + c) << ((m % 4) * 8);
+ ++m;
+ }
reg[1] = (m << 8);
}
@@ -3988,35 +4475,37 @@ nv50_linkage_validate(struct nv50_context *nv50)
/* if light_twoside is active, it seems FFC0_ID == BFC0_ID is bad */
if (nv50->rasterizer->pipe.light_twoside) {
- vpo = &vp->cfg.two_side[0];
+ struct nv50_sreg4 *vpo = &vp->cfg.two_side[0];
+ struct nv50_sreg4 *fpi = &fp->cfg.two_side[0];
- m = nv50_sreg4_map(map, m, lin, &fp->cfg.two_side[0], &vpo[0]);
- m = nv50_sreg4_map(map, m, lin, &fp->cfg.two_side[1], &vpo[1]);
+ m = nv50_vec4_map(map, m, zval, lin, &fpi[0], &vpo[0]);
+ m = nv50_vec4_map(map, m, zval, lin, &fpi[1], &vpo[1]);
}
reg[0] += m - 4; /* adjust FFC0 id */
reg[4] |= m << 8; /* set mid where 'normal' FP inputs start */
- for (i = 0; i < fp->cfg.io_nr; i++) {
- ubyte sn = fp->info.input_semantic_name[fp->cfg.io[i].id];
- ubyte si = fp->info.input_semantic_index[fp->cfg.io[i].id];
-
- /* position must be mapped first */
- assert(i == 0 || sn != TGSI_SEMANTIC_POSITION);
-
+ for (i = 0; i < fp->cfg.in_nr; i++) {
/* maybe even remove these from cfg.io */
- if (sn == TGSI_SEMANTIC_POSITION || sn == TGSI_SEMANTIC_FACE)
+ if (fp->cfg.in[i].sn == TGSI_SEMANTIC_POSITION ||
+ fp->cfg.in[i].sn == TGSI_SEMANTIC_FACE)
continue;
- /* VP outputs and vp->cfg.io are in the same order */
- for (n = 0; n < vp->info.num_outputs; ++n) {
- if (vp->info.output_semantic_name[n] == sn &&
- vp->info.output_semantic_index[n] == si)
+ for (n = 0; n < vp->cfg.out_nr; ++n)
+ if (vp->cfg.out[n].sn == fp->cfg.in[i].sn &&
+ vp->cfg.out[n].si == fp->cfg.in[i].si)
break;
- }
- vpo = (n < vp->info.num_outputs) ? &vp->cfg.io[n] : &dummy;
- m = nv50_sreg4_map(map, m, lin, &fp->cfg.io[i], vpo);
+ m = nv50_vec4_map(map, m, zval, lin, &fp->cfg.in[i],
+ (n < vp->cfg.out_nr) ?
+ &vp->cfg.out[n] : &dummy);
+ }
+ /* PrimitiveID either is replaced by the system value, or
+ * written by the geometry shader into an output register
+ */
+ if (fp->cfg.prim_id < 0x40) {
+ map[m / 4] |= vp->cfg.prim_id << ((m % 4) * 8);
+ reg[5] = m++;
}
if (nv50->rasterizer->pipe.point_size_per_vertex) {
@@ -4024,14 +4513,28 @@ nv50_linkage_validate(struct nv50_context *nv50)
reg[3] = (m++ << 4) | 1;
}
- /* now fill the stateobj */
- so = so_new(6, 58, 0);
+ /* now fill the stateobj (at most 28 so_data) */
+ so = so_new(10, 54, 0);
n = (m + 3) / 4;
- so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1);
- so_data (so, m);
- so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), n);
- so_datap (so, map, n);
+ assert(m <= 32);
+ if (vp->type == PIPE_SHADER_GEOMETRY) {
+ so_method(so, tesla, NV50TCL_GP_RESULT_MAP_SIZE, 1);
+ so_data (so, m);
+ so_method(so, tesla, NV50TCL_GP_RESULT_MAP(0), n);
+ so_datap (so, map, n);
+ } else {
+ so_method(so, tesla, NV50TCL_VP_GP_BUILTIN_ATTR_EN, 1);
+ so_data (so, vp->cfg.regs[0]);
+
+ so_method(so, tesla, NV50TCL_MAP_SEMANTIC_4, 1);
+ so_data (so, reg[5]);
+
+ so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1);
+ so_data (so, m);
+ so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), n);
+ so_datap (so, map, n);
+ }
so_method(so, tesla, NV50TCL_MAP_SEMANTIC_0, 4);
so_datap (so, reg, 4);
@@ -4043,14 +4546,85 @@ nv50_linkage_validate(struct nv50_context *nv50)
so_datap (so, lin, 4);
if (nv50->rasterizer->pipe.point_sprite) {
- nv50_pntc_replace(nv50, pcrd, (reg[4] >> 8) & 0xff);
+ so_method(so, tesla, NV50TCL_POINT_SPRITE_CTRL, 1);
+ so_data (so,
+ nv50_pntc_replace(nv50, pcrd, (reg[4] >> 8) & 0xff));
so_method(so, tesla, NV50TCL_POINT_COORD_REPLACE_MAP(0), 8);
so_datap (so, pcrd, 8);
}
- so_ref(so, &nv50->state.programs);
- so_ref(NULL, &so);
+ so_method(so, tesla, NV50TCL_GP_ENABLE, 1);
+ so_data (so, (vp->type == PIPE_SHADER_GEOMETRY) ? 1 : 0);
+
+ so_ref(so, &nv50->state.fp_linkage);
+ so_ref(NULL, &so);
+}
+
+static int
+construct_vp_gp_mapping(uint32_t *map32, int m,
+ struct nv50_program *vp, struct nv50_program *gp)
+{
+ uint8_t *map = (uint8_t *)map32;
+ int i, j, c;
+
+ for (i = 0; i < gp->cfg.in_nr; ++i) {
+ uint8_t oid, mv = 0, mg = gp->cfg.in[i].mask;
+
+ for (j = 0; j < vp->cfg.out_nr; ++j) {
+ if (vp->cfg.out[j].sn == gp->cfg.in[i].sn &&
+ vp->cfg.out[j].si == gp->cfg.in[i].si) {
+ mv = vp->cfg.out[j].mask;
+ oid = vp->cfg.out[j].hw;
+ break;
+ }
+ }
+
+ for (c = 0; c < 4; ++c, mv >>= 1, mg >>= 1) {
+ if (mg & mv & 1)
+ map[m++] = oid;
+ else
+ if (mg & 1)
+ map[m++] = (c == 3) ? 0x41 : 0x40;
+ oid += mv & 1;
+ }
+ }
+ return m;
+}
+
+void
+nv50_gp_linkage_validate(struct nv50_context *nv50)
+{
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nouveau_stateobj *so;
+ struct nv50_program *vp = nv50->vertprog;
+ struct nv50_program *gp = nv50->geomprog;
+ uint32_t map[16];
+ int m = 0;
+
+ if (!gp) {
+ so_ref(NULL, &nv50->state.gp_linkage);
+ return;
+ }
+ memset(map, 0, sizeof(map));
+
+ m = construct_vp_gp_mapping(map, m, vp, gp);
+
+ so = so_new(3, 24 - 3, 0);
+
+ so_method(so, tesla, NV50TCL_VP_GP_BUILTIN_ATTR_EN, 1);
+ so_data (so, vp->cfg.regs[0] | gp->cfg.regs[0]);
+
+ assert(m <= 32);
+ so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1);
+ so_data (so, m);
+
+ m = (m + 3) / 4;
+ so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), m);
+ so_datap (so, map, m);
+
+ so_ref(so, &nv50->state.gp_linkage);
+ so_ref(NULL, &so);
}
void
diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h
index 461fec1d89c..1e3ad6bff05 100644
--- a/src/gallium/drivers/nv50/nv50_program.h
+++ b/src/gallium/drivers/nv50/nv50_program.h
@@ -16,11 +16,13 @@ struct nv50_program_exec {
};
struct nv50_sreg4 {
- uint8_t hw;
- uint8_t id; /* tgsi index, nv50 needs them sorted: flat ones last */
+ uint8_t hw; /* hw index, nv50 wants flat FP inputs last */
+ uint8_t id; /* tgsi index */
uint8_t mask;
boolean linear;
+
+ ubyte sn, si; /* semantic name & index */
};
struct nv50_program {
@@ -49,16 +51,24 @@ struct nv50_program {
uint32_t regs[4];
/* for VPs, io_nr doesn't count 'private' results (PSIZ etc.) */
- unsigned io_nr;
- struct nv50_sreg4 io[PIPE_MAX_SHADER_OUTPUTS];
+ unsigned in_nr, out_nr;
+ struct nv50_sreg4 in[PIPE_MAX_SHADER_INPUTS];
+ struct nv50_sreg4 out[PIPE_MAX_SHADER_OUTPUTS];
/* FP colour inputs, VP/GP back colour outputs */
struct nv50_sreg4 two_side[2];
- /* VP only */
+ /* GP only */
+ unsigned vert_count;
+ uint8_t prim_type;
+
+ /* VP & GP only */
uint8_t clpd, clpd_nr;
uint8_t psiz;
uint8_t edgeflag_in;
+
+ /* FP & GP only */
+ uint8_t prim_id;
} cfg;
};
diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c
index 5d9e18218ae..5a4ab3508b8 100644
--- a/src/gallium/drivers/nv50/nv50_query.c
+++ b/src/gallium/drivers/nv50/nv50_query.c
@@ -111,7 +111,7 @@ nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq,
if (!q->ready) {
ret = nouveau_bo_map(q->bo, NOUVEAU_BO_RD |
- wait ? 0 : NOUVEAU_BO_NOWAIT);
+ (wait ? 0 : NOUVEAU_BO_NOWAIT));
if (ret)
return false;
q->result = ((uint32_t *)q->bo->map)[1];
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index 28e2b35deaa..73205652cc4 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -167,7 +167,7 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
struct nv50_screen *screen = nv50_screen(pscreen);
unsigned i;
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < 3; i++) {
if (screen->constbuf_parm[i])
nouveau_bo_ref(NULL, &screen->constbuf_parm[i]);
}
@@ -329,7 +329,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
so_ref(NULL, &so);
/* Static tesla init */
- so = so_new(40, 84, 20);
+ so = so_new(44, 90, 22);
so_method(so, screen->tesla, NV50TCL_COND_MODE, 1);
so_data (so, NV50TCL_COND_MODE_ALWAYS);
@@ -352,10 +352,11 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
so_data (so, 0xf);
/* max TIC (bits 4:8) & TSC (ignored) bindings, per program type */
- so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(0), 1);
- so_data (so, 0x54);
- so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(2), 1);
- so_data (so, 0x54);
+ for (i = 0; i < 3; ++i) {
+ so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(i), 1);
+ so_data (so, 0x54);
+ }
+
/* origin is top left (set to 1 for bottom left) */
so_method(so, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1);
so_data (so, 0);
@@ -370,7 +371,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
return NULL;
}
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < 3; i++) {
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (128 * 4) * 4,
&screen->constbuf_parm[i]);
if (ret) {
@@ -406,22 +407,33 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000001 | (NV50_CB_PMISC << 12));
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
+ so_data (so, 0x00000021 | (NV50_CB_PMISC << 12));
+ so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000031 | (NV50_CB_PMISC << 12));
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
- so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM |
- NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
- so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM |
- NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, (NV50_CB_PVP << 16) | 0x00000800);
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000101 | (NV50_CB_PVP << 12));
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
- so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM |
- NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
- so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM |
- NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, (NV50_CB_PGP << 16) | 0x00000800);
+ so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
+ so_data (so, 0x00000121 | (NV50_CB_PGP << 12));
+
+ so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, (NV50_CB_PFP << 16) | 0x00000800);
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000131 | (NV50_CB_PFP << 12));
diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h
index a038a4e3c2a..7a155ca9c45 100644
--- a/src/gallium/drivers/nv50/nv50_screen.h
+++ b/src/gallium/drivers/nv50/nv50_screen.h
@@ -18,10 +18,10 @@ struct nv50_screen {
struct nouveau_notifier *sync;
struct nouveau_bo *constbuf_misc[1];
- struct nouveau_bo *constbuf_parm[2];
+ struct nouveau_bo *constbuf_parm[PIPE_SHADER_TYPES];
struct nouveau_resource *immd_heap[1];
- struct nouveau_resource *parm_heap[2];
+ struct nouveau_resource *parm_heap[PIPE_SHADER_TYPES];
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 1f67df814b1..6ab33be663d 100644
--- a/src/gallium/drivers/nv50/nv50_state.c
+++ b/src/gallium/drivers/nv50/nv50_state.c
@@ -531,7 +531,7 @@ nv50_vp_state_delete(struct pipe_context *pipe, void *hwcso)
struct nv50_program *p = hwcso;
nv50_program_destroy(nv50, p);
- FREE((void*)p->pipe.tokens);
+ FREE((void *)p->pipe.tokens);
FREE(p);
}
@@ -563,7 +563,39 @@ nv50_fp_state_delete(struct pipe_context *pipe, void *hwcso)
struct nv50_program *p = hwcso;
nv50_program_destroy(nv50, p);
- FREE((void*)p->pipe.tokens);
+ FREE((void *)p->pipe.tokens);
+ FREE(p);
+}
+
+static void *
+nv50_gp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv50_program *p = CALLOC_STRUCT(nv50_program);
+
+ p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ p->type = PIPE_SHADER_GEOMETRY;
+ tgsi_scan_shader(p->pipe.tokens, &p->info);
+ return (void *)p;
+}
+
+static void
+nv50_gp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->fragprog = hwcso;
+ nv50->dirty |= NV50_NEW_GEOMPROG;
+}
+
+static void
+nv50_gp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nv50_program *p = hwcso;
+
+ nv50_program_destroy(nv50, p);
+ FREE((void *)p->pipe.tokens);
FREE(p);
}
@@ -585,17 +617,21 @@ nv50_set_clip_state(struct pipe_context *pipe,
static void
nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv50_context *nv50 = nv50_context(pipe);
if (shader == PIPE_SHADER_VERTEX) {
- nv50->constbuf[PIPE_SHADER_VERTEX] = buf->buffer;
+ nv50->constbuf[PIPE_SHADER_VERTEX] = buf;
nv50->dirty |= NV50_NEW_VERTPROG_CB;
} else
if (shader == PIPE_SHADER_FRAGMENT) {
- nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer;
+ nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf;
nv50->dirty |= NV50_NEW_FRAGPROG_CB;
+ } else
+ if (shader == PIPE_SHADER_GEOMETRY) {
+ nv50->constbuf[PIPE_SHADER_GEOMETRY] = buf;
+ nv50->dirty |= NV50_NEW_GEOMPROG_CB;
}
}
@@ -696,6 +732,10 @@ nv50_init_state_functions(struct nv50_context *nv50)
nv50->pipe.bind_fs_state = nv50_fp_state_bind;
nv50->pipe.delete_fs_state = nv50_fp_state_delete;
+ nv50->pipe.create_gs_state = nv50_gp_state_create;
+ nv50->pipe.bind_gs_state = nv50_gp_state_bind;
+ nv50->pipe.delete_gs_state = nv50_gp_state_delete;
+
nv50->pipe.set_blend_color = nv50_set_blend_color;
nv50->pipe.set_clip_state = nv50_set_clip_state;
nv50->pipe.set_constant_buffer = nv50_set_constant_buffer;
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c
index f83232f43cf..fcd07b59cd6 100644
--- a/src/gallium/drivers/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -199,6 +199,8 @@ nv50_state_emit(struct nv50_context *nv50)
nv50->state.dirty |= NV50_NEW_VERTPROG;
if (nv50->state.fragprog)
nv50->state.dirty |= NV50_NEW_FRAGPROG;
+ if (nv50->state.geomprog)
+ nv50->state.dirty |= NV50_NEW_GEOMPROG;
if (nv50->state.rast)
nv50->state.dirty |= NV50_NEW_RASTERIZER;
if (nv50->state.blend_colour)
@@ -228,9 +230,14 @@ nv50_state_emit(struct nv50_context *nv50)
so_emit(chan, nv50->state.vertprog);
if (nv50->state.dirty & NV50_NEW_FRAGPROG)
so_emit(chan, nv50->state.fragprog);
+ if (nv50->state.dirty & NV50_NEW_GEOMPROG && nv50->state.geomprog)
+ so_emit(chan, nv50->state.geomprog);
if (nv50->state.dirty & (NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
- NV50_NEW_RASTERIZER))
- so_emit(chan, nv50->state.programs);
+ NV50_NEW_GEOMPROG | NV50_NEW_RASTERIZER))
+ so_emit(chan, nv50->state.fp_linkage);
+ if ((nv50->state.dirty & (NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG))
+ && nv50->state.gp_linkage)
+ so_emit(chan, nv50->state.gp_linkage);
if (nv50->state.dirty & NV50_NEW_RASTERIZER)
so_emit(chan, nv50->state.rast);
if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR)
@@ -291,9 +298,15 @@ nv50_state_validate(struct nv50_context *nv50)
if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB))
nv50_fragprog_validate(nv50);
+ if (nv50->dirty & (NV50_NEW_GEOMPROG | NV50_NEW_GEOMPROG_CB))
+ nv50_geomprog_validate(nv50);
+
if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
- NV50_NEW_RASTERIZER))
- nv50_linkage_validate(nv50);
+ NV50_NEW_GEOMPROG | NV50_NEW_RASTERIZER))
+ nv50_fp_linkage_validate(nv50);
+
+ if (nv50->dirty & (NV50_NEW_GEOMPROG | NV50_NEW_VERTPROG))
+ nv50_gp_linkage_validate(nv50);
if (nv50->dirty & NV50_NEW_RASTERIZER)
so_ref(nv50->rasterizer->so, &nv50->state.rast);
@@ -400,8 +413,9 @@ viewport_uptodate:
for (i = 0; i < PIPE_SHADER_TYPES; ++i)
nr += nv50->sampler_nr[i];
- so = so_new(1+ 5 * PIPE_SHADER_TYPES, 1+ 19 * PIPE_SHADER_TYPES
- + nr * 8, PIPE_SHADER_TYPES * 2);
+ so = so_new(1 + 5 * PIPE_SHADER_TYPES,
+ 1 + 19 * PIPE_SHADER_TYPES + nr * 8,
+ PIPE_SHADER_TYPES * 2);
nv50_validate_samplers(nv50, so, PIPE_SHADER_VERTEX);
nv50_validate_samplers(nv50, so, PIPE_SHADER_FRAGMENT);
diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c
index bef548b7286..871536dca9b 100644
--- a/src/gallium/drivers/nv50/nv50_tex.c
+++ b/src/gallium/drivers/nv50/nv50_tex.c
@@ -155,7 +155,7 @@ static boolean
nv50_validate_textures(struct nv50_context *nv50, struct nouveau_stateobj *so,
unsigned p)
{
- static const unsigned p_remap[PIPE_SHADER_TYPES] = { 0, 2 };
+ static const unsigned p_remap[PIPE_SHADER_TYPES] = { 0, 2, 1 };
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
struct nouveau_grobj *tesla = nv50->screen->tesla;
diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c
index f2e510fba61..89a94d2fe81 100644
--- a/src/gallium/drivers/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nv50/nv50_vbo.c
@@ -55,6 +55,14 @@ nv50_prim(unsigned mode)
case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS;
case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP;
case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON;
+ case PIPE_PRIM_LINES_ADJACENCY:
+ return NV50TCL_VERTEX_BEGIN_LINES_ADJACENCY;
+ case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+ return NV50TCL_VERTEX_BEGIN_LINE_STRIP_ADJACENCY;
+ case PIPE_PRIM_TRIANGLES_ADJACENCY:
+ return NV50TCL_VERTEX_BEGIN_TRIANGLES_ADJACENCY;
+ case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+ return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP_ADJACENCY;
default:
break;
}
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index ffe066d5369..c14414fff6b 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -27,9 +27,9 @@
static void r300_blitter_save_states(struct r300_context* r300)
{
- util_blitter_save_blend(r300->blitter, r300->blend_state);
- util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state);
- util_blitter_save_rasterizer(r300->blitter, r300->rs_state);
+ util_blitter_save_blend(r300->blitter, r300->blend_state.state);
+ util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state.state);
+ util_blitter_save_rasterizer(r300->blitter, r300->rs_state.state);
util_blitter_save_fragment_shader(r300->blitter, r300->fs);
util_blitter_save_vertex_shader(r300->blitter, r300->vs);
}
diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c
index 51fdb82ff34..92de297ef1d 100644
--- a/src/gallium/drivers/r300/r300_chipset.c
+++ b/src/gallium/drivers/r300/r300_chipset.c
@@ -33,6 +33,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
/* Reasonable defaults */
caps->num_vert_fpus = 4;
caps->has_tcl = debug_get_bool_option("RADEON_NO_TCL", FALSE) ? FALSE : TRUE;
+ caps->is_r400 = FALSE;
caps->is_r500 = FALSE;
caps->high_second_pipe = FALSE;
@@ -123,6 +124,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x4A54:
caps->family = CHIP_FAMILY_R420;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x5548:
@@ -136,6 +138,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5D57:
caps->family = CHIP_FAMILY_R423;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x554C:
@@ -147,6 +150,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5D4A:
caps->family = CHIP_FAMILY_R430;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x5D4C:
@@ -157,6 +161,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5D52:
caps->family = CHIP_FAMILY_R480;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x4B48:
@@ -166,6 +171,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x4B4C:
caps->family = CHIP_FAMILY_R481;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x5E4C:
@@ -182,6 +188,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5E4D:
caps->family = CHIP_FAMILY_RV410;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x5954:
@@ -212,6 +219,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x791F:
caps->family = CHIP_FAMILY_RS690;
caps->has_tcl = FALSE;
+ caps->is_r400 = TRUE;
break;
case 0x793F:
@@ -219,6 +227,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x7942:
caps->family = CHIP_FAMILY_RS600;
caps->has_tcl = FALSE;
+ caps->is_r400 = TRUE;
break;
case 0x796C:
@@ -227,6 +236,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x796F:
caps->family = CHIP_FAMILY_RS740;
caps->has_tcl = FALSE;
+ caps->is_r400 = TRUE;
break;
case 0x7100:
diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h
index 0633a8b8a72..28084864929 100644
--- a/src/gallium/drivers/r300/r300_chipset.h
+++ b/src/gallium/drivers/r300/r300_chipset.h
@@ -40,11 +40,18 @@ struct r300_capabilities {
unsigned num_z_pipes;
/* Whether or not TCL is physically present */
boolean has_tcl;
+ /* Whether or not this is R400. The differences compared to their R3xx
+ * cousins are:
+ * - Extended fragment shader registers
+ * - Blend LTE/GTE thresholds */
+ boolean is_r400;
/* Whether or not this is an RV515 or newer; R500s have many differences
* that require extra consideration, compared to their R3xx cousins:
* - Extra bit of width and height on texture sizes
* - Blend color is split across two registers
- * - Universal Shader (US) block used for fragment shaders */
+ * - Blend LTE/GTE thresholds
+ * - Universal Shader (US) block used for fragment shaders
+ * - FP16 blending and multisampling */
boolean is_r500;
/* Whether or not the second pixel pipe is accessed with the high bit */
boolean high_second_pipe;
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index d5c2d63d393..5e4f6552c36 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -30,6 +30,7 @@
#include "r300_blit.h"
#include "r300_context.h"
+#include "r300_emit.h"
#include "r300_flush.h"
#include "r300_query.h"
#include "r300_render.h"
@@ -69,11 +70,13 @@ static void r300_destroy_context(struct pipe_context* context)
FREE(query);
}
- FREE(r300->blend_color_state);
+ FREE(r300->blend_color_state.state);
+ FREE(r300->clip_state.state);
FREE(r300->rs_block);
- FREE(r300->scissor_state);
+ FREE(r300->scissor_state.state);
FREE(r300->vertex_info);
- FREE(r300->viewport_state);
+ FREE(r300->viewport_state.state);
+ FREE(r300->ztop_state.state);
FREE(r300);
}
@@ -107,6 +110,35 @@ static void r300_flush_cb(void *data)
cs_context_copy->context.flush(&cs_context_copy->context, 0, NULL);
}
+#define R300_INIT_ATOM(atomname, atomsize) \
+ r300->atomname##_state.name = #atomname; \
+ r300->atomname##_state.state = NULL; \
+ r300->atomname##_state.size = atomsize; \
+ r300->atomname##_state.emit = r300_emit_##atomname##_state; \
+ r300->atomname##_state.dirty = FALSE; \
+ insert_at_tail(&r300->atom_list, &r300->atomname##_state);
+
+static void r300_setup_atoms(struct r300_context* r300)
+{
+ /* Create the actual atom list.
+ *
+ * Each atom is examined and emitted in the order it appears here, which
+ * can affect performance and conformance if not handled with care.
+ *
+ * Some atoms never change size, others change every emit. This is just
+ * an upper bound on each atom, to keep the emission machinery from
+ * underallocating space. */
+ make_empty_list(&r300->atom_list);
+ 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(scissor, 3);
+ R300_INIT_ATOM(viewport, 9);
+}
+
struct pipe_context* r300_create_context(struct pipe_screen* screen,
struct radeon_winsys* radeon_winsys)
{
@@ -155,11 +187,15 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300->shader_hash_table = util_hash_table_create(r300_shader_key_hash,
r300_shader_key_compare);
- r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state);
+ 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->scissor_state = CALLOC_STRUCT(r300_scissor_state);
+ r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state);
r300->vertex_info = CALLOC_STRUCT(r300_vertex_info);
- r300->viewport_state = CALLOC_STRUCT(r300_viewport_state);
+ r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state);
+ r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state);
/* Open up the OQ BO. */
r300->oqbo = screen->buffer_create(screen, 4096,
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 232530b7dc4..682b9179c83 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -30,9 +30,28 @@
#include "pipe/p_context.h"
#include "pipe/p_inlines.h"
+struct r300_context;
+
struct r300_fragment_shader;
struct r300_vertex_shader;
+struct r300_atom {
+ /* List pointers. */
+ struct r300_atom *prev, *next;
+ /* Name, for debugging. */
+ const char* name;
+ /* Opaque state. */
+ void* state;
+ /* Emit the state to the context. */
+ void (*emit)(struct r300_context*, void*);
+ /* Upper bound on number of dwords to emit. */
+ unsigned size;
+ /* Whether this atom should be emitted. */
+ boolean dirty;
+ /* Another dirty flag that is never automatically cleared. */
+ boolean always_dirty;
+};
+
struct r300_blend_state {
uint32_t blend_control; /* R300_RB3D_CBLEND: 0x4e04 */
uint32_t alpha_blend_control; /* R300_RB3D_ABLEND: 0x4e08 */
@@ -62,11 +81,6 @@ struct r300_rs_state {
/* Draw-specific rasterizer state */
struct pipe_rasterizer_state rs;
- /* Whether or not to enable the VTE. This is referenced at the very
- * last moment during emission of VTE state, to decide whether or not
- * the VTE should be used for transformation. */
- boolean enable_vte;
-
uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */
uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */
uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */
@@ -102,19 +116,6 @@ struct r300_sampler_state {
unsigned min_lod, max_lod;
};
-struct r300_scissor_regs {
- uint32_t top_left; /* R300_SC_SCISSORS_TL: 0x43e0 */
- uint32_t bottom_right; /* R300_SC_SCISSORS_BR: 0x43e4 */
-
- /* Whether everything is culled by scissoring. */
- boolean empty_area;
-};
-
-struct r300_scissor_state {
- struct r300_scissor_regs framebuffer;
- struct r300_scissor_regs scissor;
-};
-
struct r300_texture_state {
uint32_t format0; /* R300_TX_FORMAT0: 0x4480 */
uint32_t format1; /* R300_TX_FORMAT1: 0x44c0 */
@@ -135,24 +136,17 @@ struct r300_ztop_state {
uint32_t z_buffer_top; /* R300_ZB_ZTOP: 0x4f14 */
};
-#define R300_NEW_BLEND 0x00000001
-#define R300_NEW_BLEND_COLOR 0x00000002
-#define R300_NEW_CLIP 0x00000004
-#define R300_NEW_DSA 0x00000008
#define R300_NEW_FRAMEBUFFERS 0x00000010
#define R300_NEW_FRAGMENT_SHADER 0x00000020
#define R300_NEW_FRAGMENT_SHADER_CONSTANTS 0x00000040
-#define R300_NEW_RASTERIZER 0x00000080
#define R300_NEW_RS_BLOCK 0x00000100
#define R300_NEW_SAMPLER 0x00000200
#define R300_ANY_NEW_SAMPLERS 0x0001fe00
-#define R300_NEW_SCISSOR 0x00020000
#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_VIEWPORT 0x20000000
#define R300_NEW_QUERY 0x40000000
#define R300_NEW_KITCHEN_SINK 0x7fffffff
@@ -194,6 +188,12 @@ struct r300_query {
struct r300_query* next;
};
+enum r300_buffer_tiling {
+ R300_BUFFER_LINEAR = 0,
+ R300_BUFFER_TILED,
+ R300_BUFFER_SQUARETILED
+};
+
struct r300_texture {
/* Parent class */
struct pipe_texture tex;
@@ -230,6 +230,9 @@ struct r300_texture {
/* Registers carrying texture format data. */
struct r300_texture_state state;
+
+ /* Buffer tiling */
+ enum r300_buffer_tiling microtile, macrotile;
};
struct r300_vertex_info {
@@ -273,38 +276,40 @@ struct r300_context {
struct r300_vertex_info* vertex_info;
/* Various CSO state objects. */
+ /* Beginning of atom list. */
+ struct r300_atom atom_list;
/* Blend state. */
- struct r300_blend_state* blend_state;
+ struct r300_atom blend_state;
/* Blend color state. */
- struct r300_blend_color_state* blend_color_state;
+ struct r300_atom blend_color_state;
/* User clip planes. */
- struct pipe_clip_state clip_state;
+ struct r300_atom clip_state;
/* Shader constants. */
struct r300_constant_buffer shader_constants[PIPE_SHADER_TYPES];
/* Depth, stencil, and alpha state. */
- struct r300_dsa_state* dsa_state;
+ 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;
/* Rasterizer state. */
- struct r300_rs_state* rs_state;
+ struct r300_atom rs_state;
/* RS block state. */
struct r300_rs_block* rs_block;
/* Sampler states. */
struct r300_sampler_state* sampler_states[8];
int sampler_count;
/* Scissor state. */
- struct r300_scissor_state* scissor_state;
+ struct r300_atom scissor_state;
/* Texture states. */
struct r300_texture* textures[8];
int texture_count;
/* Vertex shader. */
struct r300_vertex_shader* vs;
/* Viewport state. */
- struct r300_viewport_state* viewport_state;
+ struct r300_atom viewport_state;
/* ZTOP state. */
- struct r300_ztop_state ztop_state;
+ struct r300_atom ztop_state;
/* Vertex buffers for Gallium. */
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
@@ -317,6 +322,8 @@ struct r300_context {
uint32_t dirty_state;
/* Flag indicating whether or not the HW is dirty. */
uint32_t dirty_hw;
+ /* Whether the TCL engine should be in bypass mode. */
+ boolean tcl_bypass;
/** Combination of DBG_xxx flags */
unsigned debug;
diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h
index d142fee0502..151f72b0fe4 100644
--- a/src/gallium/drivers/r300/r300_cs.h
+++ b/src/gallium/drivers/r300/r300_cs.h
@@ -52,7 +52,7 @@
#define CS_LOCALS(context) \
struct r300_context* const cs_context_copy = (context); \
struct radeon_winsys* cs_winsys = cs_context_copy->winsys; \
- int cs_count = 0;
+ int cs_count = 0; (void) cs_count;
#define CHECK_CS(size) \
assert(cs_winsys->check_cs(cs_winsys, (size)))
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index f8bfa714fef..9f93327e598 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -25,6 +25,7 @@
#include "util/u_format.h"
#include "util/u_math.h"
+#include "util/u_simple_list.h"
#include "r300_context.h"
#include "r300_cs.h"
@@ -36,11 +37,13 @@
#include "r300_texture.h"
#include "r300_vs.h"
-void r300_emit_blend_state(struct r300_context* r300,
- struct r300_blend_state* blend)
+void r300_emit_blend_state(struct r300_context* r300, void* state)
{
+ struct r300_blend_state* blend = (struct r300_blend_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) {
OUT_CS(blend->blend_control);
@@ -52,14 +55,13 @@ void r300_emit_blend_state(struct r300_context* r300,
OUT_CS(0);
/* XXX also disable fastfill here once it's supported */
}
- OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop);
OUT_CS_REG(R300_RB3D_DITHER_CTL, blend->dither);
END_CS;
}
-void r300_emit_blend_color_state(struct r300_context* r300,
- struct r300_blend_color_state* bc)
+void r300_emit_blend_color_state(struct r300_context* r300, void* state)
{
+ struct r300_blend_color_state* bc = (struct r300_blend_color_state*)state;
struct r300_screen* r300screen = r300_screen(r300->context.screen);
CS_LOCALS(r300);
@@ -76,9 +78,9 @@ void r300_emit_blend_color_state(struct r300_context* r300,
}
}
-void r300_emit_clip_state(struct r300_context* r300,
- struct pipe_clip_state* clip)
+void r300_emit_clip_state(struct r300_context* r300, void* state)
{
+ struct pipe_clip_state* clip = (struct pipe_clip_state*)state;
int i;
struct r300_screen* r300screen = r300_screen(r300->context.screen);
CS_LOCALS(r300);
@@ -106,13 +108,13 @@ void r300_emit_clip_state(struct r300_context* r300,
}
-void r300_emit_dsa_state(struct r300_context* r300,
- struct r300_dsa_state* dsa)
+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);
CS_LOCALS(r300);
- BEGIN_CS(r300screen->caps->is_r500 ? 10 : 8);
+ BEGIN_CS(r300screen->caps->is_r500 ? 8 : 6);
OUT_CS_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function);
/* not needed since we use the 8bit alpha ref */
@@ -131,7 +133,6 @@ void r300_emit_dsa_state(struct r300_context* r300,
}
OUT_CS(dsa->stencil_ref_mask);
- OUT_CS_REG(R300_ZB_ZTOP, r300->ztop_state.z_buffer_top);
/* XXX it seems r3xx doesn't support STENCILREFMASK_BF */
if (r300screen->caps->is_r500) {
@@ -145,6 +146,8 @@ static const float * get_shader_constant(
struct rc_constant * constant,
struct r300_constant_buffer * externals)
{
+ struct r300_viewport_state* viewport =
+ (struct r300_viewport_state*)r300->viewport_state.state;
static float vec[4] = { 0.0, 0.0, 0.0, 1.0 };
struct pipe_texture *tex;
@@ -167,30 +170,28 @@ static const float * get_shader_constant(
/* Texture compare-fail value. */
/* XXX Since Gallium doesn't support GL_ARB_shadow_ambient,
- * this is always (0,0,0,0). */
+ * this is always (0,0,0,0), right? */
case RC_STATE_SHADOW_AMBIENT:
vec[3] = 0;
break;
case RC_STATE_R300_VIEWPORT_SCALE:
- if (r300->rs_state->enable_vte) {
- vec[0] = r300->viewport_state->xscale;
- vec[1] = r300->viewport_state->yscale;
- vec[2] = r300->viewport_state->zscale;
- } else {
+ if (r300->tcl_bypass) {
vec[0] = 1;
vec[1] = 1;
vec[2] = 1;
+ } else {
+ vec[0] = viewport->xscale;
+ vec[1] = viewport->yscale;
+ vec[2] = viewport->zscale;
}
break;
case RC_STATE_R300_VIEWPORT_OFFSET:
- if (r300->rs_state->enable_vte) {
- vec[0] = r300->viewport_state->xoffset;
- vec[1] = r300->viewport_state->yoffset;
- vec[2] = r300->viewport_state->zoffset;
- } else {
- /* Zeros. */
+ if (!r300->tcl_bypass) {
+ vec[0] = viewport->xoffset;
+ vec[1] = viewport->yoffset;
+ vec[2] = viewport->zoffset;
}
break;
@@ -419,8 +420,10 @@ void r300_emit_fb_state(struct r300_context* r300,
OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1);
OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level] |
- r300_translate_colorformat(tex->tex.format), 0,
- RADEON_GEM_DOMAIN_VRAM, 0);
+ r300_translate_colorformat(tex->tex.format) |
+ R300_COLOR_TILE(tex->macrotile) |
+ R300_COLOR_MICROTILE(tex->microtile),
+ 0, RADEON_GEM_DOMAIN_VRAM, 0);
OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i),
r300_translate_out_fmt(surf->format));
@@ -443,8 +446,10 @@ void r300_emit_fb_state(struct r300_context* r300,
OUT_CS_REG(R300_ZB_FORMAT, r300_translate_zsformat(tex->tex.format));
OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
- OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level], 0,
- RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level] |
+ R300_DEPTHMACROTILE(tex->macrotile) |
+ R300_DEPTHMICROTILE(tex->microtile),
+ 0, RADEON_GEM_DOMAIN_VRAM, 0);
}
END_CS;
@@ -576,8 +581,9 @@ void r300_emit_query_end(struct r300_context* r300)
r300_emit_query_finish(r300, query);
}
-void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs)
+void r300_emit_rs_state(struct r300_context* r300, void* state)
{
+ struct r300_rs_state* rs = (struct r300_rs_state*)state;
CS_LOCALS(r300);
BEGIN_CS(22);
@@ -640,26 +646,47 @@ void r300_emit_rs_block_state(struct r300_context* r300,
END_CS;
}
-static void r300_emit_scissor_regs(struct r300_context* r300,
- struct r300_scissor_regs* scissor)
+void r300_emit_scissor_state(struct r300_context* r300, void* state)
{
+ unsigned minx, miny, maxx, maxy;
+ uint32_t top_left, bottom_right;
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state;
CS_LOCALS(r300);
- BEGIN_CS(3);
- OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
- OUT_CS(scissor->top_left);
- OUT_CS(scissor->bottom_right);
- END_CS;
-}
+ minx = miny = 0;
+ maxx = r300->framebuffer_state.width;
+ maxy = r300->framebuffer_state.height;
-void r300_emit_scissor_state(struct r300_context* r300,
- struct r300_scissor_state* scissor)
-{
- if (r300->rs_state->rs.scissor) {
- r300_emit_scissor_regs(r300, &scissor->scissor);
+ if (((struct r300_rs_state*)r300->rs_state.state)->rs.scissor) {
+ minx = MAX2(minx, scissor->minx);
+ miny = MAX2(miny, scissor->miny);
+ maxx = MIN2(maxx, scissor->maxx);
+ maxy = MIN2(maxy, scissor->maxy);
+ }
+
+ if (r300screen->caps->is_r500) {
+ top_left =
+ (minx << R300_SCISSORS_X_SHIFT) |
+ (miny << R300_SCISSORS_Y_SHIFT);
+ bottom_right =
+ ((maxx - 1) << R300_SCISSORS_X_SHIFT) |
+ ((maxy - 1) << R300_SCISSORS_Y_SHIFT);
} else {
- r300_emit_scissor_regs(r300, &scissor->framebuffer);
+ /* Offset of 1440 in non-R500 chipsets. */
+ top_left =
+ ((minx + 1440) << R300_SCISSORS_X_SHIFT) |
+ ((miny + 1440) << R300_SCISSORS_Y_SHIFT);
+ bottom_right =
+ (((maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) |
+ (((maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT);
}
+
+ BEGIN_CS(3);
+ OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
+ OUT_CS(top_left);
+ OUT_CS(bottom_right);
+ END_CS;
}
void r300_emit_texture(struct r300_context* r300,
@@ -695,8 +722,10 @@ void r300_emit_texture(struct r300_context* r300,
OUT_CS_REG(R300_TX_FORMAT1_0 + (offset * 4), tex->state.format1);
OUT_CS_REG(R300_TX_FORMAT2_0 + (offset * 4), tex->state.format2);
OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (offset * 4), 1);
- OUT_CS_RELOC(tex->buffer, 0,
- RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ OUT_CS_RELOC(tex->buffer,
+ R300_TXO_MACRO_TILE(tex->macrotile) |
+ R300_TXO_MICRO_TILE(tex->microtile),
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0);
END_CS;
}
@@ -762,32 +791,6 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset)
END_CS;
}
-#if 0
-void r300_emit_draw_packet(struct r300_context* r300)
-{
- CS_LOCALS(r300);
-
- DBG(r300, DBG_DRAW, "r300: Preparing vertex buffer %p for render, "
- "vertex size %d\n", r300->vbo,
- r300->vertex_info->vinfo.size);
- /* Set the pointer to our vertex buffer. The emitted values are this:
- * PACKET3 [3D_LOAD_VBPNTR]
- * COUNT [1]
- * FORMAT [size | stride << 8]
- * OFFSET [offset into BO]
- * VBPNTR [relocated BO]
- */
- BEGIN_CS(7);
- OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3);
- OUT_CS(1);
- OUT_CS(r300->vertex_info->vinfo.size |
- (r300->vertex_info->vinfo.size << 8));
- OUT_CS(r300->vbo_offset);
- OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0);
- END_CS;
-}
-#endif
-
void r300_emit_vertex_format_state(struct r300_context* r300)
{
int i;
@@ -912,26 +915,27 @@ void r300_emit_vs_constant_buffer(struct r300_context* r300,
END_CS;
}
-void r300_emit_viewport_state(struct r300_context* r300,
- struct r300_viewport_state* viewport)
+void r300_emit_viewport_state(struct r300_context* r300, void* state)
{
+ struct r300_viewport_state* viewport = (struct r300_viewport_state*)state;
CS_LOCALS(r300);
- BEGIN_CS(9);
- OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6);
- OUT_CS_32F(viewport->xscale);
- OUT_CS_32F(viewport->xoffset);
- OUT_CS_32F(viewport->yscale);
- OUT_CS_32F(viewport->yoffset);
- OUT_CS_32F(viewport->zscale);
- OUT_CS_32F(viewport->zoffset);
-
- if (r300->rs_state->enable_vte) {
- OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control);
- } else {
+ if (r300->tcl_bypass) {
+ BEGIN_CS(2);
OUT_CS_REG(R300_VAP_VTE_CNTL, 0);
+ END_CS;
+ } else {
+ BEGIN_CS(9);
+ OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6);
+ OUT_CS_32F(viewport->xscale);
+ OUT_CS_32F(viewport->xoffset);
+ OUT_CS_32F(viewport->yscale);
+ OUT_CS_32F(viewport->yoffset);
+ OUT_CS_32F(viewport->zscale);
+ OUT_CS_32F(viewport->zoffset);
+ OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control);
+ END_CS;
}
- END_CS;
}
void r300_emit_texture_count(struct r300_context* r300)
@@ -955,6 +959,16 @@ void r300_emit_texture_count(struct r300_context* r300)
}
+void r300_emit_ztop_state(struct r300_context* r300, void* state)
+{
+ struct r300_ztop_state* ztop = (struct r300_ztop_state*)state;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(2);
+ OUT_CS_REG(R300_ZB_ZTOP, ztop->z_buffer_top);
+ END_CS;
+}
+
void r300_flush_textures(struct r300_context* r300)
{
CS_LOCALS(r300);
@@ -978,18 +992,24 @@ void r300_emit_dirty_state(struct r300_context* r300)
{
struct r300_screen* r300screen = r300_screen(r300->context.screen);
struct r300_texture* tex;
- int i, dirty_tex = 0;
+ struct r300_atom* atom;
+ unsigned i, dwords = 1024;
+ int dirty_tex = 0;
boolean invalid = FALSE;
- if (!(r300->dirty_state)) {
- return;
+ /* 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;
+ }
}
- /* Check size of CS. */
- /* Make sure we have at least 8*1024 spare dwords. */
+ /* 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, 8*1024)) {
+ if (!r300->winsys->check_cs(r300->winsys, dwords)) {
r300->context.flush(&r300->context, 0, NULL);
}
@@ -1029,10 +1049,12 @@ validate:
}
}
/* ...occlusion query buffer... */
- if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo,
- 0, RADEON_GEM_DOMAIN_GTT)) {
- r300->context.flush(&r300->context, 0, NULL);
- goto validate;
+ if (r300->dirty_state & R300_NEW_QUERY) {
+ if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo,
+ 0, RADEON_GEM_DOMAIN_GTT)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ goto validate;
+ }
}
/* ...and vertex buffer. */
if (r300->vbo) {
@@ -1060,24 +1082,11 @@ validate:
r300->dirty_state &= ~R300_NEW_QUERY;
}
- if (r300->dirty_state & R300_NEW_BLEND) {
- r300_emit_blend_state(r300, r300->blend_state);
- r300->dirty_state &= ~R300_NEW_BLEND;
- }
-
- if (r300->dirty_state & R300_NEW_BLEND_COLOR) {
- r300_emit_blend_color_state(r300, r300->blend_color_state);
- r300->dirty_state &= ~R300_NEW_BLEND_COLOR;
- }
-
- if (r300->dirty_state & R300_NEW_CLIP) {
- r300_emit_clip_state(r300, &r300->clip_state);
- r300->dirty_state &= ~R300_NEW_CLIP;
- }
-
- if (r300->dirty_state & R300_NEW_DSA) {
- r300_emit_dsa_state(r300, r300->dsa_state);
- r300->dirty_state &= ~R300_NEW_DSA;
+ foreach(atom, &r300->atom_list) {
+ if (atom->dirty || atom->always_dirty) {
+ atom->emit(r300, atom->state);
+ atom->dirty = FALSE;
+ }
}
if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) {
@@ -1106,21 +1115,11 @@ validate:
r300->dirty_state &= ~R300_NEW_FRAMEBUFFERS;
}
- if (r300->dirty_state & R300_NEW_RASTERIZER) {
- r300_emit_rs_state(r300, r300->rs_state);
- r300->dirty_state &= ~R300_NEW_RASTERIZER;
- }
-
if (r300->dirty_state & R300_NEW_RS_BLOCK) {
r300_emit_rs_block_state(r300, r300->rs_block);
r300->dirty_state &= ~R300_NEW_RS_BLOCK;
}
- if (r300->dirty_state & R300_NEW_SCISSOR) {
- r300_emit_scissor_state(r300, r300->scissor_state);
- r300->dirty_state &= ~R300_NEW_SCISSOR;
- }
-
/* Samplers and textures are tracked separately but emitted together. */
if (r300->dirty_state &
(R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES)) {
@@ -1142,11 +1141,6 @@ validate:
r300->dirty_state &= ~(R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES);
}
- if (r300->dirty_state & R300_NEW_VIEWPORT) {
- r300_emit_viewport_state(r300, r300->viewport_state);
- r300->dirty_state &= ~R300_NEW_VIEWPORT;
- }
-
if (dirty_tex) {
r300_flush_textures(r300);
}
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 3797d3d332a..05a6bfeae86 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -31,17 +31,13 @@ struct r300_vertex_program_code;
void r300_emit_aos(struct r300_context* r300, unsigned offset);
-void r300_emit_blend_state(struct r300_context* r300,
- struct r300_blend_state* blend);
+void r300_emit_blend_state(struct r300_context* r300, void* state);
-void r300_emit_blend_color_state(struct r300_context* r300,
- struct r300_blend_color_state* bc);
+void r300_emit_blend_color_state(struct r300_context* r300, void* state);
-void r300_emit_clip_state(struct r300_context* r300,
- struct pipe_clip_state* clip);
+void r300_emit_clip_state(struct r300_context* r300, void* state);
-void r300_emit_dsa_state(struct r300_context* r300,
- struct r300_dsa_state* dsa);
+void r300_emit_dsa_state(struct r300_context* r300, void* state);
void r300_emit_fragment_program_code(struct r300_context* r300,
struct rX00_fragment_program_code* generic_code);
@@ -63,13 +59,12 @@ void r300_emit_query_begin(struct r300_context* r300,
void r300_emit_query_end(struct r300_context* r300);
-void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs);
+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_scissor_state(struct r300_context* r300,
- struct r300_scissor_state* scissor);
+void r300_emit_scissor_state(struct r300_context* r300, void* state);
void r300_emit_texture(struct r300_context* r300,
struct r300_sampler_state* sampler,
@@ -89,11 +84,12 @@ void r300_emit_vs_constant_buffer(struct r300_context* r300,
void r300_emit_vertex_shader(struct r300_context* r300,
struct r300_vertex_shader* vs);
-void r300_emit_viewport_state(struct r300_context* r300,
- struct r300_viewport_state* viewport);
+void r300_emit_viewport_state(struct r300_context* r300, void* state);
void r300_emit_texture_count(struct r300_context* r300);
+void r300_emit_ztop_state(struct r300_context* r300, void* state);
+
void r300_flush_textures(struct r300_context* r300);
/* Emit all dirty state. */
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index 14a08241fc4..59819cb1061 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -37,8 +37,10 @@ static void r300_flush(struct pipe_context* pipe,
{
struct r300_context *r300 = r300_context(pipe);
struct r300_query *query;
+ struct r300_atom *atom;
CS_LOCALS(r300);
+ (void) cs_count;
/* We probably need to flush Draw, but we may have been called from
* within Draw. This feels kludgy, but it might be the best thing.
*
@@ -54,7 +56,15 @@ static void r300_flush(struct pipe_context* pipe,
r300_emit_invariant_state(r300);
r300->dirty_state = R300_NEW_KITCHEN_SINK;
r300->dirty_hw = 0;
+
+ /* New kitchen sink, baby. */
+ foreach(atom, &r300->atom_list) {
+ if (atom->state) {
+ atom->dirty = TRUE;
+ }
+ }
}
+
/* reset flushed query */
foreach(query, &r300->query_list) {
query->flushed = TRUE;
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index 034bfc15cf9..361813891fb 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -1619,18 +1619,20 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R300_TX_OFFSET_5 0x4554
#define R300_TX_OFFSET_6 0x4558
#define R300_TX_OFFSET_7 0x455C
- /* BEGIN: Guess from R200 */
+
# define R300_TXO_ENDIAN_NO_SWAP (0 << 0)
# define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0)
# define R300_TXO_ENDIAN_WORD_SWAP (2 << 0)
# define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0)
-# define R300_TXO_MACRO_TILE (1 << 2)
+# define R300_TXO_MACRO_TILE_LINEAR (0 << 2)
+# define R300_TXO_MACRO_TILE_TILED (1 << 2)
+# define R300_TXO_MACRO_TILE(x) ((x) << 2)
# define R300_TXO_MICRO_TILE_LINEAR (0 << 3)
-# define R300_TXO_MICRO_TILE (1 << 3)
-# define R300_TXO_MICRO_TILE_SQUARE (2 << 3)
+# define R300_TXO_MICRO_TILE_TILED (1 << 3)
+# define R300_TXO_MICRO_TILE_TILED_SQUARE (2 << 3)
+# define R300_TXO_MICRO_TILE(x) ((x) << 3)
# define R300_TXO_OFFSET_MASK 0xffffffe0
# define R300_TXO_OFFSET_SHIFT 5
- /* END: Guess from R200 */
/* 32 bit chroma key */
#define R300_TX_CHROMA_KEY_0 0x4580
@@ -2283,9 +2285,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_COLORPITCH_MASK 0x00003FFE
# define R300_COLOR_TILE_DISABLE (0 << 16)
# define R300_COLOR_TILE_ENABLE (1 << 16)
+# define R300_COLOR_TILE(x) ((x) << 16)
# define R300_COLOR_MICROTILE_DISABLE (0 << 17)
# define R300_COLOR_MICROTILE_ENABLE (1 << 17)
# define R300_COLOR_MICROTILE_ENABLE_SQUARE (2 << 17) /* Only available in 16-bit */
+# define R300_COLOR_MICROTILE(x) ((x) << 17)
# define R300_COLOR_ENDIAN_NO_SWAP (0 << 19)
# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 19)
# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 19)
@@ -2544,9 +2548,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_DEPTHPITCH_MASK 0x00003FFC
# define R300_DEPTHMACROTILE_DISABLE (0 << 16)
# define R300_DEPTHMACROTILE_ENABLE (1 << 16)
+# define R300_DEPTHMACROTILE(x) ((x) << 16)
# define R300_DEPTHMICROTILE_LINEAR (0 << 17)
# define R300_DEPTHMICROTILE_TILED (1 << 17)
# define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17)
+# define R300_DEPTHMICROTILE(x) ((x) << 17)
# define R300_DEPTHENDIAN_NO_SWAP (0 << 18)
# define R300_DEPTHENDIAN_WORD_SWAP (1 << 18)
# define R300_DEPTHENDIAN_DWORD_SWAP (2 << 18)
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index a4ac9ad9a7b..710d850163f 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -26,6 +26,8 @@
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
+#include "indices/u_indices.h"
+
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
@@ -69,16 +71,11 @@ uint32_t r300_translate_primitive(unsigned prim)
}
}
-static boolean r300_nothing_to_draw(struct r300_context *r300)
-{
- return r300->rs_state->rs.scissor &&
- r300->scissor_state->scissor.empty_area;
-}
-
static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300,
unsigned mode)
{
- uint32_t color_control = r300->rs_state->color_control;
+ struct r300_rs_state* rs = (struct r300_rs_state*)r300->rs_state.state;
+ uint32_t color_control = rs->color_control;
/* By default (see r300_state.c:r300_create_rs_state) color_control is
* initialized to provoking the first vertex.
@@ -98,7 +95,7 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300,
* ~ C.
*/
- if (r300->rs_state->rs.flatshade_first) {
+ if (rs->rs.flatshade_first) {
switch (mode) {
case PIPE_PRIM_TRIANGLE_FAN:
color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_SECOND;
@@ -119,6 +116,44 @@ 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)
+{
+ struct pipe_buffer* vbo = r300->vertex_buffer[0].buffer;
+ unsigned vertex_size = r300->vertex_buffer[0].stride / sizeof(float);
+ unsigned i;
+ uint32_t* map;
+ 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);
+
+ BEGIN_CS(10 + count * vertex_size);
+ OUT_CS_REG(R300_GA_COLOR_CONTROL,
+ r300_provoking_vertex_fixes(r300, mode));
+ OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
+ OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0);
+ OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1);
+ OUT_CS_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");
+ }
+ //debug_printf("r300: 0x%08x\n", *map);
+ OUT_CS(*map);
+ map++;
+ }
+ END_CS;
+
+ pipe_buffer_unmap(r300->context.screen, vbo);
+}
+
static void r300_emit_draw_arrays(struct r300_context *r300,
unsigned mode,
unsigned count)
@@ -212,17 +247,54 @@ validate:
return TRUE;
}
+static struct pipe_buffer* r300_translate_elts(struct r300_context* r300,
+ struct pipe_buffer* elts,
+ unsigned* size,
+ unsigned* mode,
+ 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);
+
+ 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);
+
+ 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);
+
+ pipe_buffer_unmap(screen, elts);
+ pipe_buffer_unmap(screen, new_elts);
+
+ *size = out_index_size;
+ *mode = out_prim;
+ *count = out_nr;
+
+ return new_elts;
+}
+
/* This is the fast-path drawing & emission for HW TCL. */
void r300_draw_range_elements(struct pipe_context* pipe,
- struct pipe_buffer* indexBuffer,
- unsigned indexSize,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count)
+ struct pipe_buffer* indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
{
struct r300_context* r300 = r300_context(pipe);
+ struct pipe_buffer* orgIndexBuffer = indexBuffer;
if (!u_trim_pipe_prim(mode, &count)) {
return;
@@ -235,23 +307,24 @@ void r300_draw_range_elements(struct pipe_context* pipe,
return;
}
- if (r300_nothing_to_draw(r300)) {
- return;
- }
-
r300_update_derived_state(r300);
if (!r300_setup_vertex_buffers(r300)) {
return;
}
+ if (indexSize == 1) {
+ indexBuffer = r300_translate_elts(r300, indexBuffer,
+ &indexSize, &mode, &count);
+ }
+
if (!r300->winsys->add_buffer(r300->winsys, indexBuffer,
RADEON_GEM_DOMAIN_GTT, 0)) {
- return;
+ goto cleanup;
}
if (!r300->winsys->validate(r300->winsys)) {
- return;
+ goto cleanup;
}
r300_emit_dirty_state(r300);
@@ -260,6 +333,11 @@ void r300_draw_range_elements(struct pipe_context* pipe,
r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex,
mode, start, count);
+
+cleanup:
+ if (indexBuffer != orgIndexBuffer) {
+ pipe->screen->buffer_destroy(indexBuffer);
+ }
}
/* Simple helpers for context setup. Should probably be moved to util. */
@@ -273,7 +351,7 @@ void r300_draw_elements(struct pipe_context* pipe,
}
void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
- unsigned start, unsigned count)
+ unsigned start, unsigned count)
{
struct r300_context* r300 = r300_context(pipe);
@@ -288,10 +366,6 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
return;
}
- if (r300_nothing_to_draw(r300)) {
- return;
- }
-
r300_update_derived_state(r300);
if (!r300_setup_vertex_buffers(r300)) {
@@ -300,9 +374,12 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
r300_emit_dirty_state(r300);
- r300_emit_aos(r300, start);
-
- r300_emit_draw_arrays(r300, mode, count);
+ if (FALSE && count <= 4 && r300->vertex_buffer_count == 1) {
+ r300_emit_draw_immediate(r300, mode, start, count);
+ } else {
+ r300_emit_aos(r300, start);
+ r300_emit_draw_arrays(r300, mode, count);
+ }
}
/****************************************************************************
@@ -323,10 +400,6 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe,
return;
}
- if (r300_nothing_to_draw(r300)) {
- return;
- }
-
for (i = 0; i < r300->vertex_buffer_count; i++) {
void* buf = pipe_buffer_map(pipe->screen,
r300->vertex_buffer[i].buffer,
@@ -368,10 +441,6 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe,
return;
}
- if (r300_nothing_to_draw(r300)) {
- return;
- }
-
for (i = 0; i < r300->vertex_buffer_count; i++) {
void* buf = pipe_buffer_map(pipe->screen,
r300->vertex_buffer[i].buffer,
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index a145a7f18a5..60ad763cf48 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -317,8 +317,8 @@ static void r300_bind_blend_state(struct pipe_context* pipe,
{
struct r300_context* r300 = r300_context(pipe);
- r300->blend_state = (struct r300_blend_state*)state;
- r300->dirty_state |= R300_NEW_BLEND;
+ r300->blend_state.state = state;
+ r300->blend_state.dirty = TRUE;
}
/* Free blend state. */
@@ -340,20 +340,24 @@ static void r300_set_blend_color(struct pipe_context* pipe,
const struct pipe_blend_color* color)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_screen* r300screen = r300_screen(pipe->screen);
+ struct r300_blend_color_state* state =
+ (struct r300_blend_color_state*)r300->blend_color_state.state;
union util_color uc;
util_pack_color(color->color, PIPE_FORMAT_A8R8G8B8_UNORM, &uc);
- r300->blend_color_state->blend_color = uc.ui;
+ state->blend_color = uc.ui;
/* XXX if FP16 blending is enabled, we should use the FP16 format */
- r300->blend_color_state->blend_color_red_alpha =
+ state->blend_color_red_alpha =
float_to_fixed10(color->color[0]) |
(float_to_fixed10(color->color[3]) << 16);
- r300->blend_color_state->blend_color_green_blue =
+ state->blend_color_green_blue =
float_to_fixed10(color->color[2]) |
(float_to_fixed10(color->color[1]) << 16);
- r300->dirty_state |= R300_NEW_BLEND_COLOR;
+ r300->blend_color_state.size = r300screen->caps->is_r500 ? 3 : 2;
+ r300->blend_color_state.dirty = TRUE;
}
static void r300_set_clip_state(struct pipe_context* pipe,
@@ -362,12 +366,15 @@ static void r300_set_clip_state(struct pipe_context* pipe,
struct r300_context* r300 = r300_context(pipe);
if (r300_screen(pipe->screen)->caps->has_tcl) {
- r300->clip_state = *state;
- r300->dirty_state |= R300_NEW_CLIP;
+ memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state));
+ r300->clip_state.size = 29;
} else {
draw_flush(r300->draw);
draw_set_clip_state(r300->draw, state);
+ r300->clip_state.size = 2;
}
+
+ r300->clip_state.dirty = TRUE;
}
/* Create a new depth, stencil, and alpha state based on the CSO dsa state.
@@ -460,9 +467,11 @@ static void r300_bind_dsa_state(struct pipe_context* pipe,
void* state)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_screen* r300screen = r300_screen(pipe->screen);
- r300->dsa_state = (struct r300_dsa_state*)state;
- r300->dirty_state |= R300_NEW_DSA;
+ r300->dsa_state.state = state;
+ r300->dsa_state.size = r300screen->caps->is_r500 ? 8 : 6;
+ r300->dsa_state.dirty = TRUE;
}
/* Free DSA state. */
@@ -472,37 +481,11 @@ static void r300_delete_dsa_state(struct pipe_context* pipe,
FREE(state);
}
-static void r300_set_scissor_regs(const struct pipe_scissor_state* state,
- struct r300_scissor_regs *scissor,
- boolean is_r500)
-{
- if (is_r500) {
- scissor->top_left =
- (state->minx << R300_SCISSORS_X_SHIFT) |
- (state->miny << R300_SCISSORS_Y_SHIFT);
- scissor->bottom_right =
- ((state->maxx - 1) << R300_SCISSORS_X_SHIFT) |
- ((state->maxy - 1) << R300_SCISSORS_Y_SHIFT);
- } else {
- /* Offset of 1440 in non-R500 chipsets. */
- scissor->top_left =
- ((state->minx + 1440) << R300_SCISSORS_X_SHIFT) |
- ((state->miny + 1440) << R300_SCISSORS_Y_SHIFT);
- scissor->bottom_right =
- (((state->maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) |
- (((state->maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT);
- }
-
- scissor->empty_area = state->minx >= state->maxx ||
- state->miny >= state->maxy;
-}
-
static void
r300_set_framebuffer_state(struct pipe_context* pipe,
const struct pipe_framebuffer_state* state)
{
struct r300_context* r300 = r300_context(pipe);
- struct pipe_scissor_state scissor;
if (r300->draw) {
draw_flush(r300->draw);
@@ -510,19 +493,12 @@ static void
r300->framebuffer_state = *state;
- scissor.minx = scissor.miny = 0;
- scissor.maxx = state->width;
- scissor.maxy = state->height;
- r300_set_scissor_regs(&scissor, &r300->scissor_state->framebuffer,
- r300_screen(r300->context.screen)->caps->is_r500);
-
/* Don't rely on the order of states being set for the first time. */
- if (!r300->rs_state || !r300->rs_state->rs.scissor) {
- r300->dirty_state |= R300_NEW_SCISSOR;
- }
r300->dirty_state |= R300_NEW_FRAMEBUFFERS;
- r300->dirty_state |= R300_NEW_BLEND;
- r300->dirty_state |= R300_NEW_DSA;
+
+ r300->blend_state.dirty = TRUE;
+ r300->dsa_state.dirty = TRUE;
+ r300->scissor_state.dirty = TRUE;
}
/* Create fragment shader state. */
@@ -601,8 +577,6 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
/* Copy rasterizer state for Draw. */
rs->rs = *state;
- rs->enable_vte = !state->bypass_vs_clip_and_viewport;
-
#ifdef PIPE_ARCH_LITTLE_ENDIAN
rs->vap_control_status = R300_VC_NO_SWAP;
#else
@@ -718,12 +692,20 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
draw_set_rasterizer_state(r300->draw, &rs->rs);
}
- r300->rs_state = rs;
+ if (rs) {
+ r300->tcl_bypass = rs->rs.bypass_vs_clip_and_viewport;
+ } else {
+ r300->tcl_bypass = FALSE;
+ }
+
+ r300->rs_state.state = rs;
+ r300->rs_state.dirty = TRUE;
+ /* XXX Why is this still needed, dammit!? */
+ r300->scissor_state.dirty = TRUE;
+ r300->viewport_state.dirty = TRUE;
+
/* XXX Clean these up when we move to atom emits */
- r300->dirty_state |= R300_NEW_RASTERIZER;
r300->dirty_state |= R300_NEW_RS_BLOCK;
- r300->dirty_state |= R300_NEW_SCISSOR;
- r300->dirty_state |= R300_NEW_VIEWPORT;
if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
}
@@ -862,49 +844,48 @@ static void r300_set_scissor_state(struct pipe_context* pipe,
{
struct r300_context* r300 = r300_context(pipe);
- r300_set_scissor_regs(state, &r300->scissor_state->scissor,
- r300_screen(r300->context.screen)->caps->is_r500);
+ memcpy(r300->scissor_state.state, state,
+ sizeof(struct pipe_scissor_state));
- /* Don't rely on the order of states being set for the first time. */
- if (!r300->rs_state || r300->rs_state->rs.scissor) {
- r300->dirty_state |= R300_NEW_SCISSOR;
- }
+ r300->scissor_state.dirty = TRUE;
}
static void r300_set_viewport_state(struct pipe_context* pipe,
const struct pipe_viewport_state* state)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_viewport_state* viewport =
+ (struct r300_viewport_state*)r300->viewport_state.state;
/* Do the transform in HW. */
- r300->viewport_state->vte_control = R300_VTX_W0_FMT;
+ viewport->vte_control = R300_VTX_W0_FMT;
if (state->scale[0] != 1.0f) {
- r300->viewport_state->xscale = state->scale[0];
- r300->viewport_state->vte_control |= R300_VPORT_X_SCALE_ENA;
+ viewport->xscale = state->scale[0];
+ viewport->vte_control |= R300_VPORT_X_SCALE_ENA;
}
if (state->scale[1] != 1.0f) {
- r300->viewport_state->yscale = state->scale[1];
- r300->viewport_state->vte_control |= R300_VPORT_Y_SCALE_ENA;
+ viewport->yscale = state->scale[1];
+ viewport->vte_control |= R300_VPORT_Y_SCALE_ENA;
}
if (state->scale[2] != 1.0f) {
- r300->viewport_state->zscale = state->scale[2];
- r300->viewport_state->vte_control |= R300_VPORT_Z_SCALE_ENA;
+ viewport->zscale = state->scale[2];
+ viewport->vte_control |= R300_VPORT_Z_SCALE_ENA;
}
if (state->translate[0] != 0.0f) {
- r300->viewport_state->xoffset = state->translate[0];
- r300->viewport_state->vte_control |= R300_VPORT_X_OFFSET_ENA;
+ viewport->xoffset = state->translate[0];
+ viewport->vte_control |= R300_VPORT_X_OFFSET_ENA;
}
if (state->translate[1] != 0.0f) {
- r300->viewport_state->yoffset = state->translate[1];
- r300->viewport_state->vte_control |= R300_VPORT_Y_OFFSET_ENA;
+ viewport->yoffset = state->translate[1];
+ viewport->vte_control |= R300_VPORT_Y_OFFSET_ENA;
}
if (state->translate[2] != 0.0f) {
- r300->viewport_state->zoffset = state->translate[2];
- r300->viewport_state->vte_control |= R300_VPORT_Z_OFFSET_ENA;
+ viewport->zoffset = state->translate[2];
+ viewport->vte_control |= R300_VPORT_Z_OFFSET_ENA;
}
- r300->dirty_state |= R300_NEW_VIEWPORT;
+ r300->viewport_state.dirty = TRUE;
if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
}
@@ -1011,22 +992,22 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader)
static void r300_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct r300_context* r300 = r300_context(pipe);
void *mapped;
- if (buf == NULL || buf->buffer->size == 0 ||
- (mapped = pipe_buffer_map(pipe->screen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)) == NULL)
+ if (buf == NULL || buf->size == 0 ||
+ (mapped = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_READ)) == NULL)
{
r300->shader_constants[shader].count = 0;
return;
}
- assert((buf->buffer->size % 4 * sizeof(float)) == 0);
- memcpy(r300->shader_constants[shader].constants, mapped, buf->buffer->size);
- r300->shader_constants[shader].count = buf->buffer->size / (4 * sizeof(float));
- pipe_buffer_unmap(pipe->screen, buf->buffer);
+ assert((buf->size % 4 * sizeof(float)) == 0);
+ memcpy(r300->shader_constants[shader].constants, mapped, buf->size);
+ r300->shader_constants[shader].count = buf->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pipe->screen, buf);
if (shader == PIPE_SHADER_VERTEX)
r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS;
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index 22660a52d9a..192846411ba 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -139,10 +139,10 @@ static void r300_vertex_psc(struct r300_context* r300)
/* If TCL is bypassed, map vertex streams to equivalent VS output
* locations. */
- if (r300->rs_state->enable_vte) {
- stream_tab = identity;
- } else {
+ if (r300->tcl_bypass) {
stream_tab = r300->vs->stream_loc_notcl;
+ } else {
+ stream_tab = identity;
}
/* Vertex shaders have no semantics on their inputs,
@@ -508,7 +508,8 @@ static boolean r300_dsa_alpha_test_enabled(struct r300_dsa_state* dsa)
static void r300_update_ztop(struct r300_context* r300)
{
- r300->ztop_state.z_buffer_top = R300_ZTOP_ENABLE;
+ struct r300_ztop_state* ztop_state =
+ (struct r300_ztop_state*)r300->ztop_state.state;
/* This is important enough that I felt it warranted a comment.
*
@@ -530,31 +531,37 @@ static void r300_update_ztop(struct r300_context* r300)
* 5) Depth writes in fragment shader
* 6) Outstanding occlusion queries
*
+ * This register causes stalls all the way from SC to CB when changed,
+ * but it is buffered on-chip so it does not hurt to write it if it has
+ * not changed.
+ *
* ~C.
*/
/* ZS writes */
- if (r300_dsa_writes_depth_stencil(r300->dsa_state) &&
- (r300_dsa_alpha_test_enabled(r300->dsa_state) || /* (1) */
- r300->fs->info.uses_kill)) { /* (2) */
- r300->ztop_state.z_buffer_top = R300_ZTOP_DISABLE;
- } else if (r300_fragment_shader_writes_depth(r300->fs)) { /* (5) */
- r300->ztop_state.z_buffer_top = R300_ZTOP_DISABLE;
- } else if (r300->query_current) { /* (6) */
- r300->ztop_state.z_buffer_top = R300_ZTOP_DISABLE;
+ if (r300_dsa_writes_depth_stencil(r300->dsa_state.state) &&
+ (r300_dsa_alpha_test_enabled(r300->dsa_state.state) ||/* (1) */
+ r300->fs->info.uses_kill)) { /* (2) */
+ ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
+ } else if (r300_fragment_shader_writes_depth(r300->fs)) { /* (5) */
+ ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
+ } else if (r300->query_current) { /* (6) */
+ ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
+ } else {
+ ztop_state->z_buffer_top = R300_ZTOP_ENABLE;
}
+
+ r300->ztop_state.dirty = TRUE;
}
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_NEW_VERTEX_FORMAT) || r300->rs_state.dirty) {
r300_update_derived_shader_state(r300);
}
- if (r300->dirty_state &
- (R300_NEW_DSA | R300_NEW_FRAGMENT_SHADER | R300_NEW_QUERY)) {
- r300_update_ztop(r300);
- }
+ r300_update_ztop(r300);
}
diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c
index f25f3ca217d..b0f309695c9 100644
--- a/src/gallium/drivers/r300/r300_state_invariant.c
+++ b/src/gallium/drivers/r300/r300_state_invariant.c
@@ -115,10 +115,12 @@ void r300_emit_invariant_state(struct r300_context* r300)
OUT_CS_REG(R300_SC_HYPERZ, 0x0000001C);
OUT_CS_REG(R300_SC_EDGERULE, 0x2DA49525);
OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0x00000000);
- if (caps->is_r500) {
+
+ if (caps->family >= CHIP_FAMILY_RV350) {
OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101);
OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE);
}
+
OUT_CS_REG(R300_ZB_BW_CNTL, 0x00000000);
OUT_CS_REG(R300_ZB_DEPTHCLEARVALUE, 0x00000000);
OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0x00000000);
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 9a96206a4dc..a9bbdd56d84 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -30,6 +30,18 @@
#include "r300_texture.h"
#include "r300_screen.h"
+#define TILE_WIDTH 0
+#define TILE_HEIGHT 1
+
+static const unsigned microblock_table[5][3][2] = {
+ /*linear tiled square-tiled */
+ {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */
+ {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */
+ {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */
+ {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */
+ {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */
+};
+
static void r300_setup_texture_state(struct r300_texture* tex, boolean is_r500)
{
struct r300_texture_state* state = &tex->state;
@@ -92,33 +104,67 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
}
/**
+ * Return the width (dim==TILE_WIDTH) or height (dim==TILE_HEIGHT) of one tile
+ * of the given texture.
+ */
+static unsigned r300_texture_get_tile_size(struct r300_texture* tex, int dim)
+{
+ unsigned pixsize, tile_size;
+
+ pixsize = util_format_get_blocksize(tex->tex.format);
+ tile_size = microblock_table[util_logbase2(pixsize)][tex->microtile][dim] *
+ (tex->macrotile == R300_BUFFER_TILED ? 8 : 1);
+
+ assert(tile_size);
+ return tile_size;
+}
+
+/**
* 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 tile_width, width;
+
if (tex->stride_override)
return tex->stride_override;
+ /* Check the level. */
if (level > tex->tex.last_level) {
debug_printf("%s: level (%u) > last_level (%u)\n", __FUNCTION__,
level, tex->tex.last_level);
return 0;
}
- return align(util_format_get_stride(tex->tex.format, u_minify(tex->tex.width0, level)), 32);
+ tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH);
+ width = align(u_minify(tex->tex.width0, level), tile_width);
+
+ /* Should already be aligned except for S3TC. */
+ return align(util_format_get_stride(tex->tex.format, width), 32);
+}
+
+static unsigned r300_texture_get_nblocksy(struct r300_texture* tex,
+ unsigned level)
+{
+ unsigned height, tile_height;
+
+ tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT);
+ height = align(u_minify(tex->tex.height0, level), tile_height);
+
+ return util_format_get_nblocksy(tex->tex.format, height);
}
static void r300_setup_miptree(struct r300_texture* tex)
{
struct pipe_texture* base = &tex->tex;
- int stride, size, layer_size;
- int i;
+ unsigned stride, size, layer_size, nblocksy, i;
- for (i = 0; i <= base->last_level; i++) {
- unsigned nblocksy = util_format_get_nblocksy(base->format, u_minify(base->height0, i));
+ debug_printf("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);
+ nblocksy = r300_texture_get_nblocksy(tex, i);
layer_size = stride * nblocksy;
if (base->target == PIPE_TEXTURE_CUBE)
@@ -132,9 +178,9 @@ static void r300_setup_miptree(struct r300_texture* tex)
tex->pitch[i] = stride / util_format_get_blocksize(base->format);
debug_printf("r300: Texture miptree: Level %d "
- "(%dx%dx%d px, pitch %d bytes)\n",
+ "(%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);
+ u_minify(base->depth0, i), stride, tex->size);
}
}
@@ -163,7 +209,7 @@ static struct pipe_texture*
r300_setup_miptree(tex);
r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500);
- tex->buffer = screen->buffer_create(screen, 1024,
+ tex->buffer = screen->buffer_create(screen, 2048,
PIPE_BUFFER_USAGE_PIXEL,
tex->size);
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index f3ac6760db5..8e017939402 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -113,8 +113,8 @@ softpipe_destroy( struct pipe_context *pipe )
}
for (i = 0; i < Elements(softpipe->constants); i++) {
- if (softpipe->constants[i].buffer) {
- pipe_buffer_reference(&softpipe->constants[i].buffer, NULL);
+ if (softpipe->constants[i]) {
+ pipe_buffer_reference(&softpipe->constants[i], NULL);
}
}
@@ -256,6 +256,8 @@ softpipe_create( struct pipe_screen *screen )
softpipe->pipe.draw_arrays = softpipe_draw_arrays;
softpipe->pipe.draw_elements = softpipe_draw_elements;
softpipe->pipe.draw_range_elements = softpipe_draw_range_elements;
+ softpipe->pipe.draw_arrays_instanced = softpipe_draw_arrays_instanced;
+ softpipe->pipe.draw_elements_instanced = softpipe_draw_elements_instanced;
softpipe->pipe.clear = softpipe_clear;
softpipe->pipe.flush = softpipe_flush;
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index 73fa744f9d4..da673c57ada 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_constant_buffer constants[PIPE_SHADER_TYPES];
+ struct pipe_buffer *constants[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
index 03d35fb3cb5..03b58d2fb72 100644
--- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
+++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
@@ -52,18 +52,18 @@ softpipe_map_constant_buffers(struct softpipe_context *sp)
uint i, vssize, gssize;
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
- if (sp->constants[i].buffer && sp->constants[i].buffer->size)
- sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i].buffer,
+ if (sp->constants[i] && sp->constants[i]->size)
+ sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i],
PIPE_BUFFER_USAGE_CPU_READ);
}
- if (sp->constants[PIPE_SHADER_VERTEX].buffer)
- vssize = sp->constants[PIPE_SHADER_VERTEX].buffer->size;
+ if (sp->constants[PIPE_SHADER_VERTEX])
+ vssize = sp->constants[PIPE_SHADER_VERTEX]->size;
else
vssize = 0;
- if (sp->constants[PIPE_SHADER_GEOMETRY].buffer)
- gssize = sp->constants[PIPE_SHADER_GEOMETRY].buffer->size;
+ if (sp->constants[PIPE_SHADER_GEOMETRY])
+ gssize = sp->constants[PIPE_SHADER_GEOMETRY]->size;
else
gssize = 0;
@@ -91,26 +91,48 @@ softpipe_unmap_constant_buffers(struct softpipe_context *sp)
draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_GEOMETRY, NULL, 0);
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
- if (sp->constants[i].buffer && sp->constants[i].buffer->size)
- ws->buffer_unmap(ws, sp->constants[i].buffer);
+ if (sp->constants[i] && sp->constants[i]->size)
+ ws->buffer_unmap(ws, sp->constants[i]);
sp->mapped_constants[i] = NULL;
}
}
+/**
+ * Draw vertex arrays, with optional indexing.
+ * Basically, map the vertex buffers (and drawing surfaces), then hand off
+ * the drawing to the 'draw' module.
+ */
+static void
+softpipe_draw_range_elements_instanced(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount);
+
+
void
softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
unsigned start, unsigned count)
{
- softpipe_draw_elements(pipe, NULL, 0, mode, start, count);
+ softpipe_draw_range_elements_instanced(pipe,
+ NULL,
+ 0,
+ 0,
+ 0xffffffff,
+ mode,
+ start,
+ count,
+ 0,
+ 1);
}
-/**
- * Draw vertex arrays, with optional indexing.
- * Basically, map the vertex buffers (and drawing surfaces), then hand off
- * the drawing to the 'draw' module.
- */
void
softpipe_draw_range_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
@@ -119,6 +141,91 @@ softpipe_draw_range_elements(struct pipe_context *pipe,
unsigned max_index,
unsigned mode, unsigned start, unsigned count)
{
+ softpipe_draw_range_elements_instanced(pipe,
+ indexBuffer,
+ indexSize,
+ min_index,
+ max_index,
+ mode,
+ start,
+ count,
+ 0,
+ 1);
+}
+
+
+void
+softpipe_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+{
+ softpipe_draw_range_elements_instanced(pipe,
+ indexBuffer,
+ indexSize,
+ 0,
+ 0xffffffff,
+ mode,
+ start,
+ count,
+ 0,
+ 1);
+}
+
+void
+softpipe_draw_arrays_instanced(struct pipe_context *pipe,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount)
+{
+ softpipe_draw_range_elements_instanced(pipe,
+ NULL,
+ 0,
+ 0,
+ 0xffffffff,
+ mode,
+ start,
+ count,
+ startInstance,
+ instanceCount);
+}
+
+void
+softpipe_draw_elements_instanced(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount)
+{
+ softpipe_draw_range_elements_instanced(pipe,
+ indexBuffer,
+ indexSize,
+ 0,
+ 0xffffffff,
+ mode,
+ start,
+ count,
+ startInstance,
+ instanceCount);
+}
+
+static void
+softpipe_draw_range_elements_instanced(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount)
+{
struct softpipe_context *sp = softpipe_context(pipe);
struct draw_context *draw = sp->draw;
unsigned i;
@@ -128,45 +235,48 @@ softpipe_draw_range_elements(struct pipe_context *pipe,
sp->reduced_api_prim = u_reduced_prim(mode);
- if (sp->dirty)
- softpipe_update_derived( sp );
+ if (sp->dirty) {
+ softpipe_update_derived(sp);
+ }
softpipe_map_transfers(sp);
softpipe_map_constant_buffers(sp);
- /*
- * Map vertex buffers
- */
+ /* Map vertex buffers */
for (i = 0; i < sp->num_vertex_buffers; i++) {
- void *buf
- = pipe_buffer_map(pipe->screen,
- sp->vertex_buffer[i].buffer,
- PIPE_BUFFER_USAGE_CPU_READ);
+ void *buf;
+
+ buf = pipe_buffer_map(pipe->screen,
+ sp->vertex_buffer[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
draw_set_mapped_vertex_buffer(draw, i, buf);
}
/* Map index buffer, if present */
if (indexBuffer) {
- void *mapped_indexes
- = pipe_buffer_map(pipe->screen, indexBuffer,
- PIPE_BUFFER_USAGE_CPU_READ);
- draw_set_mapped_element_buffer_range(draw, indexSize,
- min_index,
- max_index,
+ void *mapped_indexes;
+
+ mapped_indexes = pipe_buffer_map(pipe->screen,
+ indexBuffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer_range(draw,
+ indexSize,
+ minIndex,
+ maxIndex,
mapped_indexes);
- }
- else {
+ } else {
/* no index/element buffer */
- draw_set_mapped_element_buffer_range(draw, 0, start,
- start + count - 1, NULL);
+ draw_set_mapped_element_buffer_range(draw,
+ 0,
+ start,
+ start + count - 1,
+ NULL);
}
/* draw! */
- draw_arrays(draw, mode, start, count);
+ draw_arrays_instanced(draw, mode, start, count, startInstance, instanceCount);
- /*
- * unmap vertex/index buffers - will cause draw module to flush
- */
+ /* unmap vertex/index buffers - will cause draw module to flush */
for (i = 0; i < sp->num_vertex_buffers; i++) {
draw_set_mapped_vertex_buffer(draw, i, NULL);
pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer);
@@ -176,22 +286,8 @@ softpipe_draw_range_elements(struct pipe_context *pipe,
pipe_buffer_unmap(pipe->screen, indexBuffer);
}
-
/* Note: leave drawing surfaces mapped */
softpipe_unmap_constant_buffers(sp);
sp->dirty_render_cache = TRUE;
}
-
-
-void
-softpipe_draw_elements(struct pipe_context *pipe,
- struct pipe_buffer *indexBuffer,
- unsigned indexSize,
- unsigned mode, unsigned start, unsigned count)
-{
- softpipe_draw_range_elements( pipe, indexBuffer,
- indexSize,
- 0, 0xffffffff,
- mode, start, count );
-}
diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
index 9b18dac67bd..7f244c4fd49 100644
--- a/src/gallium/drivers/softpipe/sp_state.h
+++ b/src/gallium/drivers/softpipe/sp_state.h
@@ -139,7 +139,7 @@ void softpipe_set_clip_state( struct pipe_context *,
void softpipe_set_constant_buffer(struct pipe_context *,
uint shader, uint index,
- const struct pipe_constant_buffer *buf);
+ struct pipe_buffer *buf);
void *softpipe_create_fs_state(struct pipe_context *,
const struct pipe_shader_state *);
@@ -200,6 +200,24 @@ softpipe_draw_range_elements(struct pipe_context *pipe,
unsigned mode, unsigned start, unsigned count);
void
+softpipe_draw_arrays_instanced(struct pipe_context *pipe,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount);
+
+void
+softpipe_draw_elements_instanced(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount);
+
+void
softpipe_map_transfers(struct softpipe_context *sp);
void
diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c
index aa12bb215a8..b7ed4441b43 100644
--- a/src/gallium/drivers/softpipe/sp_state_fs.c
+++ b/src/gallium/drivers/softpipe/sp_state_fs.c
@@ -159,7 +159,7 @@ softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
void
softpipe_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
@@ -169,8 +169,7 @@ softpipe_set_constant_buffer(struct pipe_context *pipe,
draw_flush(softpipe->draw);
/* note: reference counting */
- pipe_buffer_reference(&softpipe->constants[shader].buffer,
- buf ? buf->buffer : NULL);
+ pipe_buffer_reference(&softpipe->constants[shader], buf);
softpipe->dirty |= SP_NEW_CONSTANTS;
}
diff --git a/src/gallium/drivers/svga/svga_pipe_constants.c b/src/gallium/drivers/svga/svga_pipe_constants.c
index 10e7a121892..ca2c7c49d72 100644
--- a/src/gallium/drivers/svga/svga_pipe_constants.c
+++ b/src/gallium/drivers/svga/svga_pipe_constants.c
@@ -49,7 +49,7 @@ struct svga_constbuf
static void svga_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct svga_context *svga = svga_context(pipe);
@@ -57,7 +57,7 @@ static void svga_set_constant_buffer(struct pipe_context *pipe,
assert(index == 0);
pipe_buffer_reference( &svga->curr.cb[shader],
- buf->buffer );
+ buf );
if (shader == PIPE_SHADER_FRAGMENT)
svga->dirty |= SVGA_NEW_FS_CONST_BUFFER;
diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c
index bba80a93a56..ec2886348b9 100644
--- a/src/gallium/drivers/svga/svga_state_fs.c
+++ b/src/gallium/drivers/svga/svga_state_fs.c
@@ -72,7 +72,7 @@ static enum pipe_error compile_fs( struct svga_context *svga,
struct svga_shader_result **out_result )
{
struct svga_shader_result *result;
- enum pipe_error ret;
+ enum pipe_error ret = PIPE_ERROR;
result = svga_translate_fragment_program( fs, key );
if (result == NULL) {
@@ -81,8 +81,10 @@ static enum pipe_error compile_fs( struct svga_context *svga,
}
result->id = util_bitmask_add(svga->fs_bm);
- if(result->id == UTIL_BITMASK_INVALID_INDEX)
+ if(result->id == UTIL_BITMASK_INVALID_INDEX) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
goto fail;
+ }
ret = SVGA3D_DefineShader(svga->swc,
result->id,
diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c
index ae1e77e7d44..e7e6c084321 100644
--- a/src/gallium/drivers/svga/svga_state_vs.c
+++ b/src/gallium/drivers/svga/svga_state_vs.c
@@ -71,7 +71,7 @@ static enum pipe_error compile_vs( struct svga_context *svga,
struct svga_shader_result **out_result )
{
struct svga_shader_result *result;
- enum pipe_error ret = PIPE_OK;
+ enum pipe_error ret = PIPE_ERROR;
result = svga_translate_vertex_program( vs, key );
if (result == NULL) {
@@ -80,8 +80,10 @@ static enum pipe_error compile_vs( struct svga_context *svga,
}
result->id = util_bitmask_add(svga->vs_bm);
- if(result->id == UTIL_BITMASK_INVALID_INDEX)
+ if(result->id == UTIL_BITMASK_INVALID_INDEX) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
goto fail;
+ }
ret = SVGA3D_DefineShader(svga->swc,
result->id,
@@ -200,10 +202,12 @@ static int update_zero_stride( struct svga_context *svga,
key.output_stride = 4 * sizeof(float);
key.nr_elements = 1;
+ key.element[0].type = TRANSLATE_ELEMENT_NORMAL;
key.element[0].input_format = vel->src_format;
key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
key.element[0].input_buffer = vel->vertex_buffer_index;
key.element[0].input_offset = vel->src_offset;
+ key.element[0].instance_divisor = vel->instance_divisor;
key.element[0].output_offset = const_idx * 4 * sizeof(float);
translate_key_sanitize(&key);
@@ -222,7 +226,7 @@ static int update_zero_stride( struct svga_context *svga,
translate->set_buffer(translate, vel->vertex_buffer_index,
mapped_buffer,
vbuffer->stride);
- translate->run(translate, 0, 1,
+ translate->run(translate, 0, 1, 0,
svga->curr.zero_stride_constants);
pipe_buffer_unmap(svga->pipe.screen,
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index 075e4f9a0b2..5a9f0fc6901 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -812,13 +812,13 @@ trace_context_set_clip_state(struct pipe_context *_pipe,
static INLINE void
trace_context_set_constant_buffer(struct pipe_context *_pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buffer)
+ struct pipe_buffer *buffer)
{
struct trace_context *tr_ctx = trace_context(_pipe);
struct pipe_context *pipe = tr_ctx->pipe;
if (buffer)
- trace_screen_user_buffer_update(_pipe->screen, buffer->buffer);
+ trace_screen_user_buffer_update(_pipe->screen, buffer);
trace_dump_call_begin("pipe_context", "set_constant_buffer");
@@ -827,10 +827,11 @@ trace_context_set_constant_buffer(struct pipe_context *_pipe,
trace_dump_arg(uint, index);
trace_dump_arg(constant_buffer, buffer);
+ /* XXX hmm? */
if (buffer) {
- struct pipe_constant_buffer _buffer;
- _buffer.buffer = trace_buffer_unwrap(tr_ctx, buffer->buffer);
- pipe->set_constant_buffer(pipe, shader, index, &_buffer);
+ struct pipe_buffer *_buffer;
+ _buffer = trace_buffer_unwrap(tr_ctx, buffer);
+ pipe->set_constant_buffer(pipe, shader, index, _buffer);
} else {
pipe->set_constant_buffer(pipe, shader, index, buffer);
}
diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
index 86237e03bcc..32f61f8c944 100644
--- a/src/gallium/drivers/trace/tr_dump_state.c
+++ b/src/gallium/drivers/trace/tr_dump_state.c
@@ -229,7 +229,7 @@ void trace_dump_clip_state(const struct pipe_clip_state *state)
}
-void trace_dump_constant_buffer(const struct pipe_constant_buffer *state)
+void trace_dump_constant_buffer(const struct pipe_buffer *state)
{
if (!trace_dumping_enabled_locked())
return;
@@ -241,7 +241,7 @@ void trace_dump_constant_buffer(const struct pipe_constant_buffer *state)
trace_dump_struct_begin("pipe_constant_buffer");
- trace_dump_member(buffer_ptr, state, buffer);
+ trace_dump_reference(&state->reference);
trace_dump_struct_end();
}
diff --git a/src/gallium/drivers/trace/tr_dump_state.h b/src/gallium/drivers/trace/tr_dump_state.h
index 07ad6fbb205..c7860fd6e18 100644
--- a/src/gallium/drivers/trace/tr_dump_state.h
+++ b/src/gallium/drivers/trace/tr_dump_state.h
@@ -47,7 +47,7 @@ void trace_dump_scissor_state(const struct pipe_scissor_state *state);
void trace_dump_clip_state(const struct pipe_clip_state *state);
-void trace_dump_constant_buffer(const struct pipe_constant_buffer *state);
+void trace_dump_constant_buffer(const struct pipe_buffer *state);
void trace_dump_token(const struct tgsi_token *token);
diff --git a/src/gallium/include/pipe/p_compiler.h b/src/gallium/include/pipe/p_compiler.h
index f7368bb95b3..18ebd0c9483 100644
--- a/src/gallium/include/pipe/p_compiler.h
+++ b/src/gallium/include/pipe/p_compiler.h
@@ -52,45 +52,15 @@
#endif /* _MSC_VER */
-#if defined(_MSC_VER)
-
-typedef __int8 int8_t;
-typedef unsigned __int8 uint8_t;
-typedef __int16 int16_t;
-typedef unsigned __int16 uint16_t;
-#ifndef __eglplatform_h_
-typedef __int32 int32_t;
-#endif
-typedef unsigned __int32 uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-#if defined(_WIN64)
-typedef __int64 intptr_t;
-typedef unsigned __int64 uintptr_t;
-#else
-typedef __int32 intptr_t;
-typedef unsigned __int32 uintptr_t;
-#endif
-
-#define INT64_C(__val) __val##i64
-#define UINT64_C(__val) __val##ui64
-
-#ifndef __cplusplus
-#define false 0
-#define true 1
-#define bool _Bool
-typedef int _Bool;
-#define __bool_true_false_are_defined 1
-#endif /* !__cplusplus */
-
-#else
+/*
+ * Alternative stdint.h and stdbool.h headers are supplied in include/c99 for
+ * systems that lack it.
+ */
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
#include <stdint.h>
#include <stdbool.h>
-#endif
#ifndef __HAIKU__
@@ -99,11 +69,7 @@ typedef unsigned short ushort;
#endif
typedef unsigned char ubyte;
-#if 0
-#define boolean bool
-#else
typedef unsigned char boolean;
-#endif
#ifndef TRUE
#define TRUE true
#endif
@@ -135,6 +101,17 @@ typedef unsigned char boolean;
# endif
#endif
+
+/* Function visibility */
+#ifndef PUBLIC
+# if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
+# define PUBLIC __attribute__((visibility("default")))
+# else
+# define PUBLIC
+# endif
+#endif
+
+
/* The __FUNCTION__ gcc variable is generally only used for debugging.
* If we're not using gcc, define __FUNCTION__ as a cpp symbol here.
*/
@@ -162,22 +139,33 @@ typedef unsigned char boolean;
+/* Macros for data alignment. */
#if defined(__GNUC__)
-#define ALIGN16_DECL(TYPE, NAME, SIZE) TYPE NAME##___aligned[SIZE] __attribute__(( aligned( 16 ) ))
-#define ALIGN16_ASSIGN(NAME) NAME##___aligned
-#define ALIGN16_ATTRIB __attribute__(( aligned( 16 ) ))
-#define ALIGN8_ATTRIB __attribute__(( aligned( 8 ) ))
+
+/* See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Type-Attributes.html */
+#define PIPE_ALIGN_TYPE(_alignment, _type) _type __attribute__((aligned(_alignment)))
+
+/* See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Variable-Attributes.html */
+#define PIPE_ALIGN_VAR(_alignment) __attribute__((aligned(_alignment)))
+
#if (__GNUC__ > 4 || (__GNUC__ == 4 &&__GNUC_MINOR__>1)) && !defined(PIPE_ARCH_X86_64)
-#define ALIGN_STACK __attribute__((force_align_arg_pointer))
+#define PIPE_ALIGN_STACK __attribute__((force_align_arg_pointer))
#else
-#define ALIGN_STACK
+#define PIPE_ALIGN_STACK
#endif
+
+#elif defined(_MSC_VER)
+
+/* See http://msdn.microsoft.com/en-us/library/83ythb65.aspx */
+#define PIPE_ALIGN_TYPE(_alignment, _type) __declspec(align(_alignment)) _type
+#define PIPE_ALIGN_VAR(_alignment) __declspec(align(_alignment))
+
+#define PIPE_ALIGN_STACK
+
#else
-#define ALIGN16_DECL(TYPE, NAME, SIZE) TYPE NAME##___unaligned[SIZE + 1]
-#define ALIGN16_ASSIGN(NAME) align16(NAME##___unaligned)
-#define ALIGN16_ATTRIB
-#define ALIGN8_ATTRIB
-#define ALIGN_STACK
+
+#error "Unsupported compiler"
+
#endif
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index d2f8085b421..0b8f6da2f4a 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -69,6 +69,22 @@ struct pipe_context {
unsigned indexSize,
unsigned mode, unsigned start, unsigned count);
+ void (*draw_arrays_instanced)(struct pipe_context *pipe,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount);
+
+ void (*draw_elements_instanced)(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount);
+
/* XXX: this is (probably) a temporary entrypoint, as the range
* information should be available from the vertex_buffer state.
* Using this to quickly evaluate a specialized path in the draw
@@ -170,7 +186,7 @@ struct pipe_context {
void (*set_constant_buffer)( struct pipe_context *,
uint shader, uint index,
- const struct pipe_constant_buffer *buf );
+ struct pipe_buffer *buf );
void (*set_framebuffer_state)( struct pipe_context *,
const struct pipe_framebuffer_state * );
diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h
index f0a4de5df33..b8e001a6b01 100644
--- a/src/gallium/include/pipe/p_screen.h
+++ b/src/gallium/include/pipe/p_screen.h
@@ -266,6 +266,11 @@ struct pipe_screen {
void (*video_surface_destroy)( struct pipe_video_surface *vsfc );
+ /**
+ * Do any special operations to ensure buffer size is correct
+ */
+ void (*update_buffer)( struct pipe_screen *ws,
+ void *context_private );
/**
* Do any special operations to ensure frontbuffer contents are
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 550e2abc32a..b489b044667 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -121,17 +121,18 @@ struct tgsi_declaration_range
unsigned Last : 16; /**< UINT */
};
-#define TGSI_SEMANTIC_POSITION 0
-#define TGSI_SEMANTIC_COLOR 1
-#define TGSI_SEMANTIC_BCOLOR 2 /**< back-face color */
-#define TGSI_SEMANTIC_FOG 3
-#define TGSI_SEMANTIC_PSIZE 4
-#define TGSI_SEMANTIC_GENERIC 5
-#define TGSI_SEMANTIC_NORMAL 6
-#define TGSI_SEMANTIC_FACE 7
-#define TGSI_SEMANTIC_EDGEFLAG 8
-#define TGSI_SEMANTIC_PRIMID 9
-#define TGSI_SEMANTIC_COUNT 10 /**< number of semantic values */
+#define TGSI_SEMANTIC_POSITION 0
+#define TGSI_SEMANTIC_COLOR 1
+#define TGSI_SEMANTIC_BCOLOR 2 /**< back-face color */
+#define TGSI_SEMANTIC_FOG 3
+#define TGSI_SEMANTIC_PSIZE 4
+#define TGSI_SEMANTIC_GENERIC 5
+#define TGSI_SEMANTIC_NORMAL 6
+#define TGSI_SEMANTIC_FACE 7
+#define TGSI_SEMANTIC_EDGEFLAG 8
+#define TGSI_SEMANTIC_PRIMID 9
+#define TGSI_SEMANTIC_INSTANCEID 10
+#define TGSI_SEMANTIC_COUNT 11 /**< number of semantic values */
struct tgsi_declaration_semantic
{
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 60e96b98deb..fdd29ed4492 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -66,10 +66,6 @@ extern "C" {
#define PIPE_MAX_TEXTURE_LEVELS 16
-/* fwd decls */
-struct pipe_surface;
-
-
/**
* The driver will certainly subclass this to include actual memory
* management information.
@@ -178,15 +174,6 @@ struct pipe_clip_state
};
-/**
- * Constants for vertex/fragment shaders
- */
-struct pipe_constant_buffer
-{
- struct pipe_buffer *buffer;
-};
-
-
struct pipe_shader_state
{
const struct tgsi_token *tokens;
@@ -376,6 +363,11 @@ struct pipe_vertex_element
/** Offset of this attribute, in bytes, from the start of the vertex */
unsigned src_offset;
+ /** Instance data rate divisor. 0 means this is per-vertex data,
+ * n means per-instance data used for n consecutive instances (n > 0).
+ */
+ unsigned instance_divisor;
+
/** Which vertex_buffer (as given to pipe->set_vertex_buffer()) does
* this attribute live in?
*/
diff --git a/src/gallium/include/state_tracker/drm_api.h b/src/gallium/include/state_tracker/drm_api.h
index 4d1259e1ee7..bb928928c90 100644
--- a/src/gallium/include/state_tracker/drm_api.h
+++ b/src/gallium/include/state_tracker/drm_api.h
@@ -28,6 +28,8 @@ struct drm_create_screen_arg {
struct drm_api
{
+ const char *name;
+
/**
* Special buffer functions
*/
diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c
index 1058dd38c25..0fdfa96b35a 100644
--- a/src/gallium/state_trackers/dri/dri_drawable.c
+++ b/src/gallium/state_trackers/dri/dri_drawable.c
@@ -180,6 +180,7 @@ dri_get_buffers(__DRIdrawable * dPriv)
switch (buffers[i].attachment) {
case __DRI_BUFFER_FRONT_LEFT:
+ continue;
case __DRI_BUFFER_FAKE_FRONT_LEFT:
index = ST_SURFACE_FRONT_LEFT;
format = drawable->color_format;
@@ -268,6 +269,14 @@ void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
}
void
+dri_update_buffer(struct pipe_screen *screen, void *context_private)
+{
+ struct dri_context *ctx = (struct dri_context *)context_private;
+
+ dri_get_buffers(ctx->dPriv);
+}
+
+void
dri_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_surface *surf, void *context_private)
{
@@ -364,6 +373,7 @@ 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 (visual->doubleBufferMode)
drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT;
diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h
index 80bb5d7f617..8bc59cb4c3d 100644
--- a/src/gallium/state_trackers/dri/dri_drawable.h
+++ b/src/gallium/state_trackers/dri/dri_drawable.h
@@ -81,6 +81,9 @@ dri_create_buffer(__DRIscreen * sPriv,
const __GLcontextModes * visual, boolean isPixmap);
void
+dri_update_buffer(struct pipe_screen *screen, void *context_private);
+
+void
dri_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_surface *surf, void *context_private);
diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c
index bb12baf2815..793db087ee1 100644
--- a/src/gallium/state_trackers/dri/dri_screen.c
+++ b/src/gallium/state_trackers/dri/dri_screen.c
@@ -308,6 +308,7 @@ dri_init_screen2(__DRIscreen * sPriv)
}
/* We need to hook in here */
+ screen->pipe_screen->update_buffer = dri_update_buffer;
screen->pipe_screen->flush_frontbuffer = dri_flush_frontbuffer;
driParseOptionInfo(&screen->optionCache,
diff --git a/src/gallium/state_trackers/egl_g3d/Makefile b/src/gallium/state_trackers/egl_g3d/Makefile
new file mode 100644
index 00000000000..213eb3e815b
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/Makefile
@@ -0,0 +1,72 @@
+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/common/egl_g3d.c b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
new file mode 100644
index 00000000000..51da8e19f5e
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
@@ -0,0 +1,1147 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include "pipe/p_screen.h"
+#include "util/u_memory.h"
+#include "egldriver.h"
+#include "eglcurrent.h"
+#include "eglconfigutil.h"
+#include "egllog.h"
+
+#include "native.h"
+#include "egl_g3d.h"
+#include "egl_st.h"
+
+/**
+ * Validate the draw/read surfaces of the context.
+ */
+static void
+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;
+
+ /* validate draw and/or read buffers */
+ num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
+ for (s = 0; s < num_surfaces; s++) {
+ struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
+ struct egl_g3d_surface *gsurf;
+ struct egl_g3d_buffer *gbuf;
+
+ if (s == 0) {
+ gsurf = egl_g3d_surface(gctx->base.DrawSurface);
+ gbuf = &gctx->draw;
+ }
+ else {
+ gsurf = egl_g3d_surface(gctx->base.ReadSurface);
+ gbuf = &gctx->read;
+ }
+
+ if (!gctx->force_validate) {
+ unsigned int seq_num;
+
+ gsurf->native->validate(gsurf->native,
+ gbuf->native_atts, gbuf->num_atts,
+ &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,
+ &gsurf->sequence_number, textures,
+ &gsurf->base.Width, &gsurf->base.Height);
+ for (i = 0; i < gbuf->num_atts; i++) {
+ struct pipe_texture *pt = textures[i];
+ struct pipe_surface *ps;
+
+ if (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);
+
+ if (gbuf->native_atts[i] == gsurf->render_att)
+ pipe_surface_reference(&gsurf->render_surface, ps);
+
+ pipe_surface_reference(&ps, NULL);
+ pipe_texture_reference(&pt, NULL);
+ }
+ }
+
+ gctx->stapi->st_resize_framebuffer(gbuf->st_fb,
+ gsurf->base.Width, gsurf->base.Height);
+ }
+
+ gctx->force_validate = EGL_FALSE;
+
+}
+
+/**
+ * Create a st_framebuffer.
+ */
+static struct st_framebuffer *
+create_framebuffer(_EGLContext *ctx, _EGLSurface *surf)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+ struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
+
+ return gctx->stapi->st_create_framebuffer(&gconf->native->mode,
+ gconf->native->color_format, gconf->native->depth_format,
+ gconf->native->stencil_format,
+ gsurf->base.Width, gsurf->base.Height, &gsurf->base);
+}
+
+/**
+ * Update the attachments of draw/read surfaces.
+ */
+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;
+
+ /* route draw and read buffers' attachments */
+ for (s = 0; s < 2; s++) {
+ struct egl_g3d_surface *gsurf;
+ struct egl_g3d_buffer *gbuf;
+
+ if (s == 0) {
+ gsurf = egl_g3d_surface(gctx->base.DrawSurface);
+ gbuf = &gctx->draw;
+ }
+ else {
+ gsurf = egl_g3d_surface(gctx->base.ReadSurface);
+ 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]];
+
+ /* FIXME OpenGL defaults to draw the front or back buffer when the
+ * context is single-buffered or double-buffered respectively. In EGL,
+ * however, the buffer to be drawn is determined by the surface, instead
+ * of the context. As a result, rendering to a pixmap surface with a
+ * double-buffered context does not work as expected.
+ *
+ * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt ==
+ * NATIVE_ATTACHMENT_FRONT_LEFT);
+ */
+
+ /*
+ * FIXME If the back buffer is asked for here, and the front buffer is
+ * later needed by the client API (e.g. glDrawBuffer is called to draw
+ * the front buffer), it will create a new pipe texture and draw there.
+ * One fix is to ask for both buffers here, but it would be a waste if
+ * the front buffer is never used. A better fix is to add a callback to
+ * the pipe screen with context private (just like flush_frontbuffer).
+ */
+ }
+}
+
+/**
+ * Reallocate the context's framebuffers after draw/read surfaces change.
+ */
+static EGLBoolean
+egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface);
+ struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface);
+
+ /* unreference the old framebuffers */
+ if (gctx->draw.st_fb) {
+ EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb);
+ void *priv;
+
+ priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb);
+ 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;
+ }
+
+ if (is_equal) {
+ gctx->read.st_fb = NULL;
+ gctx->draw.num_atts = 0;
+ }
+ 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;
+ }
+ }
+ }
+
+ if (!gdraw)
+ return EGL_TRUE;
+
+ /* create the draw fb */
+ if (!gctx->draw.st_fb) {
+ gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base);
+ if (!gctx->draw.st_fb)
+ return EGL_FALSE;
+ }
+
+ /* create the read fb */
+ if (!gctx->read.st_fb) {
+ if (gread != gdraw) {
+ gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base);
+ if (!gctx->read.st_fb) {
+ gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
+ gctx->draw.st_fb = NULL;
+ return EGL_FALSE;
+ }
+ }
+ else {
+ /* there is no st_reference_framebuffer... */
+ gctx->read.st_fb = gctx->draw.st_fb;
+ }
+ }
+
+ egl_g3d_route_context(dpy, &gctx->base);
+ gctx->force_validate = EGL_TRUE;
+
+ return EGL_TRUE;
+}
+
+/**
+ * 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 *
+egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ const struct egl_g3d_st *stapi;
+ EGLint idx = -1;
+
+ switch (ctx->ClientAPI) {
+ case EGL_OPENGL_ES_API:
+ switch (ctx->ClientVersion) {
+ case 1:
+ idx = EGL_G3D_ST_OPENGL_ES;
+ break;
+ case 2:
+ idx = EGL_G3D_ST_OPENGL_ES2;
+ break;
+ default:
+ _eglLog(_EGL_WARNING, "unknown client version %d",
+ ctx->ClientVersion);
+ break;
+ }
+ break;
+ case EGL_OPENVG_API:
+ idx = EGL_G3D_ST_OPENVG;
+ break;
+ case EGL_OPENGL_API:
+ idx = EGL_G3D_ST_OPENGL;
+ break;
+ default:
+ _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
+ break;
+ }
+
+ stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL;
+ return stapi;
+}
+
+/**
+ * Return an API mask that consists of the state trackers that supports the
+ * given mode.
+ *
+ * FIXME add st_is_mode_supported()?
+ */
+static EGLint
+get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask)
+{
+ EGLint check;
+
+ /* OpenGL ES 1.x and 2.x are checked together */
+ check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
+ if (api_mask & check) {
+ /* this is required by EGL, not by OpenGL ES */
+ if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode)
+ api_mask &= ~check;
+ }
+
+ check = EGL_OPENVG_BIT;
+ if (api_mask & check) {
+ /* vega st needs the depth/stencil rb */
+ if (!mode->depthBits && !mode->stencilBits)
+ api_mask &= ~check;
+ }
+
+ return api_mask;
+}
+
+#ifdef EGL_MESA_screen_surface
+
+static void
+egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ const struct native_connector **native_connectors;
+ EGLint num_connectors, i;
+
+ native_connectors =
+ gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
+ if (!num_connectors) {
+ if (native_connectors)
+ free(native_connectors);
+ return;
+ }
+
+ for (i = 0; i < num_connectors; i++) {
+ const struct native_connector *nconn = native_connectors[i];
+ struct egl_g3d_screen *gscr;
+ const struct native_mode **native_modes;
+ EGLint num_modes, j;
+
+ /* TODO support for hotplug */
+ native_modes =
+ gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
+ if (!num_modes) {
+ if (native_modes)
+ free(native_modes);
+ continue;
+ }
+
+ gscr = CALLOC_STRUCT(egl_g3d_screen);
+ if (!gscr) {
+ free(native_modes);
+ continue;
+ }
+
+ _eglInitScreen(&gscr->base);
+
+ for (j = 0; j < num_modes; j++) {
+ const struct native_mode *nmode = native_modes[j];
+ _EGLMode *mode;
+
+ mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height,
+ nmode->refresh_rate, nmode->desc);
+ if (!mode)
+ break;
+ /* gscr->native_modes and gscr->base.Modes should be consistent */
+ assert(mode == &gscr->base.Modes[j]);
+ }
+
+ gscr->native = nconn;
+ gscr->native_modes = native_modes;
+
+ _eglAddScreen(dpy, &gscr->base);
+ }
+
+ free(native_connectors);
+}
+
+#endif /* EGL_MESA_screen_surface */
+
+/**
+ * Add configs to display and return the next config ID.
+ */
+static EGLint
+egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ const struct native_config **native_configs;
+ int num_configs, i;
+
+ native_configs = gdpy->native->get_configs(gdpy->native,
+ &num_configs);
+ if (!num_configs) {
+ if (native_configs)
+ free(native_configs);
+ return id;
+ }
+
+ for (i = 0; i < num_configs; i++) {
+ EGLint api_mask;
+ struct egl_g3d_config *gconf;
+ EGLBoolean valid;
+
+ 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) {
+#ifdef EGL_MESA_screen_surface
+ /* check if scanout surface bit is set */
+ if (native_configs[i]->scanout_bit) {
+ EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE);
+ val |= EGL_SCREEN_BIT_MESA;
+ SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val);
+ }
+#endif
+ valid = _eglValidateConfig(&gconf->base, EGL_FALSE);
+ }
+ if (!valid) {
+ _eglLog(_EGL_DEBUG, "skip invalid config 0x%x",
+ native_configs[i]->mode.visualID);
+ free(gconf);
+ continue;
+ }
+
+ gconf->native = native_configs[i];
+ _eglAddConfig(dpy, &gconf->base);
+ id++;
+ }
+
+ free(native_configs);
+ return id;
+}
+
+/**
+ * Flush the front buffer of the context's draw surface.
+ */
+static void
+egl_g3d_flush_frontbuffer(struct pipe_screen *screen,
+ struct pipe_surface *surf, void *context_private)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(context_private);
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface);
+
+ if (gsurf)
+ gsurf->native->flush_frontbuffer(gsurf->native);
+}
+
+/**
+ * Re-validate the context.
+ */
+static void
+egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(context_private);
+
+ /**
+ * It is likely that the surface has changed when this function is called.
+ * Set force_validate to skip an unnecessary check.
+ */
+ gctx->force_validate = EGL_TRUE;
+ egl_g3d_validate_context(gctx->base.Display, &gctx->base);
+}
+
+static EGLBoolean
+egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ EGLint i;
+
+ _eglReleaseDisplayResources(drv, dpy);
+ _eglCleanupDisplay(dpy);
+
+ if (dpy->Screens) {
+ for (i = 0; i < dpy->NumScreens; i++) {
+ struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
+ free(gscr->native_modes);
+ free(gscr);
+ }
+ free(dpy->Screens);
+ }
+
+ if (gdpy->native)
+ gdpy->native->destroy(gdpy->native);
+
+ free(gdpy);
+ dpy->DriverData = NULL;
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
+ EGLint *major, EGLint *minor)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ struct egl_g3d_display *gdpy;
+
+ gdpy = CALLOC_STRUCT(egl_g3d_display);
+ if (!gdpy) {
+ _eglError(EGL_BAD_ALLOC, "eglInitialize");
+ goto fail;
+ }
+ dpy->DriverData = gdpy;
+
+ gdpy->native = native_create_display(dpy->NativeDisplay);
+ if (!gdpy->native) {
+ _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
+ goto fail;
+ }
+
+ gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer;
+ gdpy->native->screen->update_buffer = egl_g3d_update_buffer;
+
+ dpy->ClientAPIsMask = gdrv->api_mask;
+
+ if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
+ _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
+ goto fail;
+ }
+
+#ifdef EGL_MESA_screen_surface
+ /* enable MESA_screen_surface */
+ if (gdpy->native->modeset) {
+ dpy->Extensions.MESA_screen_surface = EGL_TRUE;
+ egl_g3d_add_screens(drv, dpy);
+ }
+#endif
+
+ *major = 1;
+ *minor = 4;
+
+ return EGL_TRUE;
+
+fail:
+ if (gdpy)
+ egl_g3d_terminate(drv, dpy);
+ return EGL_FALSE;
+}
+
+static _EGLContext *
+egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
+ _EGLContext *share, const EGLint *attribs)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_context *gshare = egl_g3d_context(share);
+ struct egl_g3d_config *gconf = egl_g3d_config(conf);
+ struct egl_g3d_context *gctx;
+ const __GLcontextModes *mode;
+
+ gctx = CALLOC_STRUCT(egl_g3d_context);
+ if (!gctx) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateContext");
+ return NULL;
+ }
+
+ if (!_eglInitContext(drv, &gctx->base, conf, attribs)) {
+ free(gctx);
+ return NULL;
+ }
+
+ gctx->stapi = egl_g3d_choose_st(drv, &gctx->base);
+ if (!gctx->stapi) {
+ free(gctx);
+ return NULL;
+ }
+
+ mode = &gconf->native->mode;
+ gctx->pipe =
+ gdpy->native->create_context(gdpy->native, (void *) &gctx->base);
+ if (!gctx->pipe) {
+ free(gctx);
+ return NULL;
+ }
+
+ gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode,
+ (gshare) ? gshare->st_ctx : NULL);
+ if (!gctx->st_ctx) {
+ gctx->pipe->destroy(gctx->pipe);
+ free(gctx);
+ return NULL;
+ }
+
+ return &gctx->base;
+}
+
+static EGLBoolean
+egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+
+ if (_eglIsContextBound(&gctx->base))
+ return EGL_TRUE;
+
+ egl_g3d_realloc_context(dpy, &gctx->base);
+
+ /* it will destroy pipe context */
+ gctx->stapi->st_destroy_context(gctx->st_ctx);
+
+ free(gctx);
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+init_surface_geometry(_EGLSurface *surf)
+{
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+
+ return gsurf->native->validate(gsurf->native, NULL, 0,
+ &gsurf->sequence_number, NULL,
+ &gsurf->base.Width, &gsurf->base.Height);
+}
+
+static _EGLSurface *
+egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLConfig *conf, EGLNativeWindowType win,
+ const EGLint *attribs)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_config *gconf = egl_g3d_config(conf);
+ struct egl_g3d_surface *gsurf;
+
+ gsurf = CALLOC_STRUCT(egl_g3d_surface);
+ if (!gsurf) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &gsurf->base, EGL_WINDOW_BIT, conf, attribs)) {
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->native =
+ gdpy->native->create_window_surface(gdpy->native, win, gconf->native);
+ if (!gsurf->native) {
+ free(gsurf);
+ return NULL;
+ }
+
+ if (!init_surface_geometry(&gsurf->base)) {
+ gsurf->native->destroy(gsurf->native);
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER ||
+ !gconf->native->mode.doubleBufferMode) ?
+ NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
+
+ return &gsurf->base;
+}
+
+static _EGLSurface *
+egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLConfig *conf, EGLNativePixmapType pix,
+ const EGLint *attribs)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_config *gconf = egl_g3d_config(conf);
+ struct egl_g3d_surface *gsurf;
+
+ gsurf = CALLOC_STRUCT(egl_g3d_surface);
+ if (!gsurf) {
+ _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &gsurf->base, EGL_PIXMAP_BIT, conf, attribs)) {
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->native =
+ gdpy->native->create_pixmap_surface(gdpy->native, pix, gconf->native);
+ if (!gsurf->native) {
+ free(gsurf);
+ return NULL;
+ }
+
+ if (!init_surface_geometry(&gsurf->base)) {
+ gsurf->native->destroy(gsurf->native);
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT;
+
+ return &gsurf->base;
+}
+
+static _EGLSurface *
+egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLConfig *conf, const EGLint *attribs)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_config *gconf = egl_g3d_config(conf);
+ struct egl_g3d_surface *gsurf;
+
+ gsurf = CALLOC_STRUCT(egl_g3d_surface);
+ if (!gsurf) {
+ _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &gsurf->base, EGL_PBUFFER_BIT, conf, attribs)) {
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->native =
+ gdpy->native->create_pbuffer_surface(gdpy->native, gconf->native,
+ gsurf->base.Width, gsurf->base.Height);
+ if (!gsurf->native) {
+ free(gsurf);
+ return NULL;
+ }
+
+ if (!init_surface_geometry(&gsurf->base)) {
+ gsurf->native->destroy(gsurf->native);
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
+ NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
+
+ return &gsurf->base;
+}
+
+static EGLBoolean
+egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
+{
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+
+ if (_eglIsSurfaceBound(&gsurf->base))
+ return EGL_TRUE;
+
+ pipe_surface_reference(&gsurf->render_surface, NULL);
+ gsurf->native->destroy(gsurf->native);
+ free(gsurf);
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+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_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))
+ return EGL_FALSE;
+
+ if (old_gctx) {
+ /* flush old context */
+ old_gctx->stapi->st_flush(old_gctx->st_ctx,
+ PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
+
+ /*
+ * The old context is no longer current, and egl_g3d_realloc_context()
+ * should be called to destroy the framebuffers. However, it is possible
+ * that it will be made current again with the same draw/read surfaces.
+ * It might be better to keep it around.
+ */
+ }
+
+ 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,
+ gctx->draw.st_fb, gctx->read.st_fb);
+ if (ok) {
+ egl_g3d_validate_context(dpy, &gctx->base);
+ if (gdraw->base.Type == EGL_WINDOW_BIT) {
+ gctx->base.WindowRenderBuffer =
+ (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ?
+ EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
+ }
+ }
+ }
+ }
+ else if (old_gctx) {
+ ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL);
+ old_gctx->base.WindowRenderBuffer = EGL_NONE;
+ }
+
+ return ok;
+}
+
+static EGLBoolean
+egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
+{
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+ _EGLContext *ctx = _eglGetCurrentContext();
+ struct egl_g3d_context *gctx = NULL;
+
+ /* no-op for pixmap or pbuffer surface */
+ if (gsurf->base.Type == EGL_PIXMAP_BIT ||
+ gsurf->base.Type == EGL_PBUFFER_BIT)
+ return EGL_TRUE;
+
+ /* or when the surface is single-buffered */
+ if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT)
+ return EGL_TRUE;
+
+ if (ctx && ctx->DrawSurface == surf)
+ gctx = egl_g3d_context(ctx);
+
+ /* flush if the surface is current */
+ if (gctx)
+ gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
+
+ /*
+ * We drew on the back buffer, unless there was no back buffer.
+ * In that case, we drew on the front buffer. Either case, we call
+ * swap_buffers.
+ */
+ if (!gsurf->native->swap_buffers(gsurf->native))
+ return EGL_FALSE;
+
+ if (gctx) {
+ struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
+
+ /* force validation if the swap method is not copy */
+ if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) {
+ gctx->force_validate = EGL_TRUE;
+ egl_g3d_validate_context(dpy, &gctx->base);
+ }
+ }
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+{
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ gctx->stapi->st_finish(gctx->st_ctx);
+ return EGL_TRUE;
+}
+
+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);
+
+ if (engine != EGL_CORE_NATIVE_ENGINE)
+ return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
+
+ if (gsurf)
+ gsurf->native->wait(gsurf->native);
+
+ return EGL_TRUE;
+}
+
+static _EGLProc
+egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ _EGLProc proc;
+ EGLint i;
+
+ for (i = 0; i < NUM_EGL_G3D_STS; i++) {
+ const struct egl_g3d_st *stapi = gdrv->stapis[i];
+ if (stapi) {
+ proc = (_EGLProc) stapi->st_get_proc_address(procname);
+ if (proc)
+ return proc;
+ }
+ }
+
+ return (_EGLProc) NULL;
+}
+
+static EGLBoolean
+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;
+ enum pipe_format target_format;
+ int target;
+
+ if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
+ return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
+ if (buffer != EGL_BACK_BUFFER)
+ return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
+ if (gsurf->base.BoundToTexture)
+ return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
+
+ switch (gsurf->base.TextureFormat) {
+ case EGL_TEXTURE_RGB:
+ target_format = PIPE_FORMAT_R8G8B8_UNORM;
+ break;
+ case EGL_TEXTURE_RGBA:
+ target_format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ break;
+ default:
+ return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ }
+
+ switch (gsurf->base.TextureTarget) {
+ case EGL_TEXTURE_2D:
+ target = ST_TEXTURE_2D;
+ break;
+ default:
+ return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ }
+
+ /* flush properly if the surface is bound */
+ if (gsurf->base.Binding) {
+ gctx = egl_g3d_context(gsurf->base.Binding);
+ 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;
+
+ gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
+ target, gsurf->base.MipmapLevel, target_format);
+ gsurf->base.BoundToTexture = EGL_TRUE;
+ }
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLSurface *surf, EGLint buffer)
+{
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+
+ if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT ||
+ !gsurf->base.BoundToTexture)
+ return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
+ if (buffer != EGL_BACK_BUFFER)
+ 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)]);
+
+ /* what if the context the surface binds to is no longer current? */
+ if (gctx)
+ gctx->stapi->st_unbind_texture_surface(gsurf->render_surface,
+ ST_TEXTURE_2D, gsurf->base.MipmapLevel);
+ }
+
+ gsurf->base.BoundToTexture = EGL_FALSE;
+
+ return EGL_TRUE;
+}
+
+#ifdef EGL_MESA_screen_surface
+
+static _EGLSurface *
+egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLConfig *conf, const EGLint *attribs)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_config *gconf = egl_g3d_config(conf);
+ struct egl_g3d_surface *gsurf;
+
+ gsurf = CALLOC_STRUCT(egl_g3d_surface);
+ if (!gsurf) {
+ _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &gsurf->base,
+ EGL_SCREEN_BIT_MESA, conf, attribs)) {
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->native =
+ gdpy->native->modeset->create_scanout_surface(gdpy->native,
+ gconf->native, gsurf->base.Width, gsurf->base.Height);
+ if (!gsurf->native) {
+ free(gsurf);
+ return NULL;
+ }
+
+ gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
+ NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
+
+ return &gsurf->base;
+}
+
+static EGLBoolean
+egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLScreen *scr, _EGLSurface *surf,
+ _EGLMode *mode)
+{
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_screen *gscr = egl_g3d_screen(scr);
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+ struct native_surface *nsurf;
+ const struct native_mode *nmode;
+ EGLBoolean changed;
+
+ if (gsurf) {
+ EGLint idx;
+
+ if (!mode)
+ return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
+ if (gsurf->base.Type != EGL_SCREEN_BIT_MESA)
+ return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA");
+ if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height)
+ return _eglError(EGL_BAD_MATCH,
+ "eglShowSurfaceMESA(surface smaller than mode size)");
+
+ /* find the index of the mode */
+ for (idx = 0; idx < gscr->base.NumModes; idx++)
+ if (mode == &gscr->base.Modes[idx])
+ break;
+ if (idx >= gscr->base.NumModes) {
+ return _eglError(EGL_BAD_MODE_MESA,
+ "eglShowSurfaceMESA(unknown mode)");
+ }
+
+ nsurf = gsurf->native;
+ nmode = gscr->native_modes[idx];
+ }
+ else {
+ if (mode)
+ return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
+
+ /* disable the screen */
+ nsurf = NULL;
+ nmode = NULL;
+ }
+
+ /* TODO surface panning by CRTC choosing */
+ changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf,
+ gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode);
+ if (changed) {
+ gscr->base.CurrentSurface = &gsurf->base;
+ gscr->base.CurrentMode = mode;
+ }
+
+ return changed;
+}
+
+#endif /* EGL_MESA_screen_surface */
+
+static void
+egl_g3d_unload(_EGLDriver *drv)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ free(gdrv);
+}
+
+_EGLDriver *
+_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());
+
+ gdrv = CALLOC_STRUCT(egl_g3d_driver);
+ if (!gdrv)
+ return NULL;
+
+ _eglInitDriverFallbacks(&gdrv->base);
+
+ gdrv->base.API.Initialize = egl_g3d_initialize;
+ gdrv->base.API.Terminate = egl_g3d_terminate;
+ gdrv->base.API.CreateContext = egl_g3d_create_context;
+ gdrv->base.API.DestroyContext = egl_g3d_destroy_context;
+ gdrv->base.API.CreateWindowSurface = egl_g3d_create_window_surface;
+ gdrv->base.API.CreatePixmapSurface = egl_g3d_create_pixmap_surface;
+ gdrv->base.API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface;
+ 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.WaitClient = egl_g3d_wait_client;
+ gdrv->base.API.WaitNative = egl_g3d_wait_native;
+ gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
+
+ gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image;
+ gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image;
+
+#ifdef EGL_MESA_screen_surface
+ gdrv->base.API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
+ gdrv->base.API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface;
+#endif
+
+ gdrv->base.Name = driver_name;
+ 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");
+
+ return &gdrv->base;
+}
diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
new file mode 100644
index 00000000000..4c8b8dfe9e0
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
@@ -0,0 +1,127 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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 _EGL_G3D_H_
+#define _EGL_G3D_H_
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_format.h"
+#include "egldriver.h"
+#include "egldisplay.h"
+#include "eglcontext.h"
+#include "eglsurface.h"
+#include "eglconfig.h"
+#include "eglscreen.h"
+#include "eglmode.h"
+
+#include "native.h"
+#include "egl_st.h"
+
+struct egl_g3d_driver {
+ _EGLDriver base;
+ const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS];
+ EGLint api_mask;
+};
+
+struct egl_g3d_display {
+ struct native_display *native;
+};
+
+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];
+};
+
+struct egl_g3d_context {
+ _EGLContext base;
+
+ const struct egl_g3d_st *stapi;
+ struct pipe_context *pipe;
+
+ struct st_context *st_ctx;
+ EGLBoolean force_validate;
+ struct egl_g3d_buffer draw, read;
+};
+
+struct egl_g3d_surface {
+ _EGLSurface base;
+ struct native_surface *native;
+ enum native_attachment render_att;
+ struct pipe_surface *render_surface;
+ unsigned int sequence_number;
+};
+
+struct egl_g3d_config {
+ _EGLConfig base;
+ const struct native_config *native;
+};
+
+struct egl_g3d_screen {
+ _EGLScreen base;
+ const struct native_connector *native;
+ const struct native_mode **native_modes;
+};
+
+static INLINE struct egl_g3d_driver *
+egl_g3d_driver(_EGLDriver *drv)
+{
+ return (struct egl_g3d_driver *) drv;
+}
+
+static INLINE struct egl_g3d_display *
+egl_g3d_display(_EGLDisplay *dpy)
+{
+ /* note that it is not direct casting */
+ return (struct egl_g3d_display *) dpy->DriverData;
+}
+
+static INLINE struct egl_g3d_context *
+egl_g3d_context(_EGLContext *ctx)
+{
+ return (struct egl_g3d_context *) ctx;
+}
+
+static INLINE struct egl_g3d_surface *
+egl_g3d_surface(_EGLSurface *surf)
+{
+ return (struct egl_g3d_surface *) surf;
+}
+
+static INLINE struct egl_g3d_config *
+egl_g3d_config(_EGLConfig *conf)
+{
+ return (struct egl_g3d_config *) conf;
+}
+
+static INLINE struct egl_g3d_screen *
+egl_g3d_screen(_EGLScreen *scr)
+{
+ return (struct egl_g3d_screen *) scr;
+}
+
+#endif /* _EGL_G3D_H_ */
diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_st.c b/src/gallium/state_trackers/egl_g3d/common/egl_st.c
new file mode 100644
index 00000000000..a88ff911cd5
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/common/egl_st.c
@@ -0,0 +1,131 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dlfcn.h>
+#include "pipe/p_compiler.h"
+#include "util/u_memory.h"
+#include "egllog.h"
+#include "EGL/egl.h" /* for EGL_api_BIT */
+
+#include "egl_st.h"
+
+#ifndef HAVE_DLADDR
+#define HAVE_DLADDR 1
+#endif
+
+#if HAVE_DLADDR
+
+static const char *
+egl_g3d_st_names[] = {
+#define ST_PUBLIC(name, ...) #name,
+#include "st_public_tmp.h"
+ NULL
+};
+
+static boolean
+egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
+{
+ st_proc *procs = (st_proc *) stapi;
+ void *handle;
+ Dl_info info;
+ const char **name;
+
+ if (!dladdr(sym, &info))
+ return FALSE;
+ handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE);
+ if (!handle)
+ return FALSE;
+
+ for (name = egl_g3d_st_names; *name; name++) {
+ st_proc proc = (st_proc) dlsym(handle, *name);
+ if (!proc) {
+ _eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname);
+ memset(stapi, 0, sizeof(*stapi));
+ dlclose(handle);
+ return FALSE;
+ }
+ *procs++ = proc;
+ }
+
+ dlclose(handle);
+ return TRUE;
+}
+
+#else /* HAVE_DLADDR */
+
+static boolean
+egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
+{
+#define ST_PUBLIC(name, ...) stapi->name = name;
+#include "st_public_tmp.h"
+ return TRUE;
+}
+
+#endif /* HAVE_DLADDR */
+
+static boolean
+egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api)
+{
+ void *handle, *sym;
+ boolean res = FALSE;
+
+ /* already initialized */
+ if (stapi->st_notify_swapbuffers != NULL)
+ return TRUE;
+
+ handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
+ if (!handle)
+ return FALSE;
+
+ sym = dlsym(handle, api);
+ if (sym && egl_g3d_fill_st(stapi, sym))
+ res = TRUE;
+
+ dlclose(handle);
+ return res;
+}
+
+static struct {
+ const char *symbol;
+ EGLint api_bit;
+} egl_g3d_st_info[NUM_EGL_G3D_STS] = {
+ { "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT },
+ { "st_api_OpenVG", EGL_OPENVG_BIT },
+ { "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT },
+ { "st_api_OpenGL", EGL_OPENGL_BIT },
+};
+
+const struct egl_g3d_st *
+egl_g3d_get_st(enum egl_g3d_st_api api)
+{
+ static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS];
+
+ if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) {
+ all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit;
+ return &all_trackers[api];
+ }
+ else {
+ return NULL;
+ }
+}
diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_st.h b/src/gallium/state_trackers/egl_g3d/common/egl_st.h
new file mode 100644
index 00000000000..8fb464bd3d7
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/common/egl_st.h
@@ -0,0 +1,73 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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 _EGL_ST_H_
+#define _EGL_ST_H_
+
+#include "GL/gl.h" /* for GL types */
+#include "GL/internal/glcore.h" /* for __GLcontextModes */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+
+/* avoid calling st functions directly */
+#if 1
+
+#define ST_SURFACE_FRONT_LEFT 0
+#define ST_SURFACE_BACK_LEFT 1
+#define ST_SURFACE_FRONT_RIGHT 2
+#define ST_SURFACE_BACK_RIGHT 3
+
+#define ST_TEXTURE_2D 0x2
+
+struct st_context;
+struct st_framebuffer;
+typedef void (*st_proc)();
+
+#else
+#include "state_tracker/st_public.h"
+#endif
+
+/* remember to update egl_g3d_get_st() when update the enums */
+enum egl_g3d_st_api {
+ EGL_G3D_ST_OPENGL_ES = 0,
+ EGL_G3D_ST_OPENVG,
+ EGL_G3D_ST_OPENGL_ES2,
+ EGL_G3D_ST_OPENGL,
+
+ NUM_EGL_G3D_STS
+};
+
+struct egl_g3d_st {
+#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__);
+#include "st_public_tmp.h"
+ /* fields must be added here */
+ EGLint api_bit;
+};
+
+const struct egl_g3d_st *
+egl_g3d_get_st(enum egl_g3d_st_api api);
+
+#endif /* _EGL_ST_H_ */
diff --git a/src/gallium/state_trackers/egl_g3d/common/native.h b/src/gallium/state_trackers/egl_g3d/common/native.h
new file mode 100644
index 00000000000..76f0e0c78ac
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/common/native.h
@@ -0,0 +1,220 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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 _NATIVE_H_
+#define _NATIVE_H_
+
+#include "EGL/egl.h" /* for EGL native types */
+#include "GL/gl.h" /* for GL types needed by __GLcontextModes */
+#include "GL/internal/glcore.h" /* for __GLcontextModes */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+/**
+ * Only color buffers are listed. The others are allocated privately through,
+ * for example, st_renderbuffer_alloc_storage().
+ */
+enum native_attachment {
+ NATIVE_ATTACHMENT_FRONT_LEFT,
+ NATIVE_ATTACHMENT_BACK_LEFT,
+ NATIVE_ATTACHMENT_FRONT_RIGHT,
+ NATIVE_ATTACHMENT_BACK_RIGHT,
+
+ NUM_NATIVE_ATTACHMENTS
+};
+
+struct native_surface {
+ void (*destroy)(struct native_surface *nsurf);
+
+ /**
+ * Swap the front and back buffers so that the back buffer is visible. It
+ * is no-op if the surface is single-buffered. The contents of the back
+ * buffer after swapping may or may not be preserved.
+ */
+ boolean (*swap_buffers)(struct native_surface *nsurf);
+
+ /**
+ * Make the front buffer visible. In some native displays, changes to the
+ * front buffer might not be visible immediately and require manual flush.
+ */
+ 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.
+ *
+ * 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.
+ */
+ boolean (*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);
+
+ /**
+ * Wait until all native commands affecting the surface has been executed.
+ */
+ void (*wait)(struct native_surface *nsurf);
+};
+
+struct native_config {
+ /* __GLcontextModes should go away some day */
+ __GLcontextModes mode;
+ enum pipe_format color_format;
+ enum pipe_format depth_format;
+ enum pipe_format stencil_format;
+
+ /* treat it as an additional flag to mode.drawableType */
+ boolean scanout_bit;
+};
+
+struct native_connector {
+ int dummy;
+};
+
+struct native_mode {
+ const char *desc;
+ int width, height;
+ int refresh_rate;
+};
+
+struct native_display_modeset;
+
+/**
+ * A pipe winsys abstracts the OS. A pipe screen abstracts the graphcis
+ * hardware. A native display consists of a pipe winsys, a pipe screen, and
+ * the native display server.
+ */
+struct native_display {
+ /**
+ * The pipe screen of the native display.
+ *
+ * Note that the "flush_frontbuffer" and "update_buffer" callbacks will be
+ * overridden.
+ */
+ struct pipe_screen *screen;
+
+ void (*destroy)(struct native_display *ndpy);
+
+ /**
+ * Get the supported configs. The configs are owned by the display, but
+ * the returned array should be free()ed.
+ *
+ * The configs will be converted to EGL config by
+ * _eglConfigFromContextModesRec and validated by _eglValidateConfig.
+ * Those failing to pass the test will be skipped.
+ */
+ const struct native_config **(*get_configs)(struct native_display *ndpy,
+ int *num_configs);
+
+ /**
+ * Create a pipe context.
+ */
+ struct pipe_context *(*create_context)(struct native_display *ndpy,
+ void *context_private);
+
+ /**
+ * Create a window surface. Required unless no config has GLX_WINDOW_BIT
+ * set.
+ */
+ struct native_surface *(*create_window_surface)(struct native_display *ndpy,
+ EGLNativeWindowType win,
+ const struct native_config *nconf);
+
+ /**
+ * Create a pixmap surface. Required unless no config has GLX_PIXMAP_BIT
+ * set.
+ */
+ struct native_surface *(*create_pixmap_surface)(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf);
+
+ /**
+ * Create a pbuffer surface. Required unless no config has GLX_PBUFFER_BIT
+ * set.
+ */
+ struct native_surface *(*create_pbuffer_surface)(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height);
+
+ const struct native_display_modeset *modeset;
+};
+
+/**
+ * Mode setting interface of the native display. It exposes the mode setting
+ * capabilities of the underlying graphics hardware.
+ */
+struct native_display_modeset {
+ /**
+ * Get the available physical connectors and the number of CRTCs.
+ */
+ const struct native_connector **(*get_connectors)(struct native_display *ndpy,
+ int *num_connectors,
+ int *num_crtcs);
+
+ /**
+ * Get the current supported modes of a connector. The returned modes may
+ * change every time this function is called and those from previous calls
+ * might become invalid.
+ */
+ const struct native_mode **(*get_modes)(struct native_display *ndpy,
+ const struct native_connector *nconn,
+ int *num_modes);
+
+ /**
+ * Create a scan-out surface. Required unless no config has
+ * GLX_SCREEN_BIT_MESA set.
+ */
+ struct native_surface *(*create_scanout_surface)(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height);
+
+ /**
+ * Program the CRTC to output the surface to the given connectors with the
+ * given mode. When surface is not given, the CRTC is disabled.
+ *
+ * This interface does not export a way to query capabilities of the CRTCs.
+ * The native display usually needs to dynamically map the index to a CRTC
+ * that supports the given connectors.
+ */
+ boolean (*program)(struct native_display *ndpy, int crtc_idx,
+ struct native_surface *nsurf, uint x, uint y,
+ const struct native_connector **nconns, int num_nconns,
+ const struct native_mode *nmode);
+};
+
+const char *
+native_get_name(void);
+
+struct native_display *
+native_create_display(EGLNativeDisplayType dpy);
+
+#endif /* _NATIVE_H_ */
diff --git a/src/gallium/state_trackers/egl_g3d/common/st_public_tmp.h b/src/gallium/state_trackers/egl_g3d/common/st_public_tmp.h
new file mode 100644
index 00000000000..507a0ec4027
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/common/st_public_tmp.h
@@ -0,0 +1,20 @@
+ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share)
+ST_PUBLIC(st_destroy_context, void, struct st_context *st)
+ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask)
+ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData)
+ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height)
+ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf)
+ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height)
+ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface)
+ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture)
+ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb)
+ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb)
+ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read)
+ST_PUBLIC(st_get_current, struct st_context *, void)
+ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence)
+ST_PUBLIC(st_finish, void, struct st_context *st)
+ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb)
+ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format)
+ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level)
+ST_PUBLIC(st_get_proc_address, st_proc, const char *procname)
+#undef ST_PUBLIC
diff --git a/src/gallium/state_trackers/egl_g3d/kms/native_kms.c b/src/gallium/state_trackers/egl_g3d/kms/native_kms.c
new file mode 100644
index 00000000000..65829fc7b3d
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/kms/native_kms.c
@@ -0,0 +1,855 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "egllog.h"
+
+#include "native_kms.h"
+
+static boolean
+kms_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)
+{
+ struct kms_surface *ksurf = kms_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);
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.last_level = 0;
+ templ.width0 = ksurf->width;
+ templ.height0 = ksurf->height;
+ templ.depth0 = 1;
+ templ.format = ksurf->color_format;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ if (ksurf->type == KMS_SURFACE_TYPE_SCANOUT)
+ templ.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
+ }
+
+ /* create textures */
+ for (i = 0; i < num_natts; i++) {
+ enum native_attachment natt = natts[i];
+
+ ptex = ksurf->textures[natt];
+ if (!ptex) {
+ ptex = screen->texture_create(screen, &templ);
+ ksurf->textures[natt] = ptex;
+ }
+
+ if (textures)
+ pipe_texture_reference(&textures[i], ptex);
+ }
+
+ if (seq_num)
+ *seq_num = ksurf->sequence_number;
+ if (width)
+ *width = ksurf->width;
+ if (height)
+ *height = ksurf->height;
+
+ return TRUE;
+}
+
+/**
+ * Add textures as DRM framebuffers.
+ */
+static boolean
+kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
+{
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ struct kms_display *kdpy = ksurf->kdpy;
+ int num_framebuffers = (need_back) ? 2 : 1;
+ int i, err;
+
+ for (i = 0; i < num_framebuffers; i++) {
+ struct kms_framebuffer *fb;
+ enum native_attachment natt;
+ unsigned int handle, stride;
+ uint block_bits;
+
+ if (i == 0) {
+ fb = &ksurf->front_fb;
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ }
+ else {
+ fb = &ksurf->back_fb;
+ natt = NATIVE_ATTACHMENT_BACK_LEFT;
+ }
+
+ if (!fb->texture) {
+ /* make sure the texture has been allocated */
+ kms_surface_validate(&ksurf->base, &natt, 1, NULL, NULL, NULL, NULL);
+ if (!ksurf->textures[natt])
+ return FALSE;
+
+ pipe_texture_reference(&fb->texture, ksurf->textures[natt]);
+ }
+
+ /* already initialized */
+ if (fb->buffer_id)
+ continue;
+
+ /* TODO detect the real value */
+ fb->is_passive = TRUE;
+
+ if (!kdpy->api->local_handle_from_texture(kdpy->api,
+ kdpy->base.screen, fb->texture, &stride, &handle))
+ return FALSE;
+
+ block_bits = util_format_get_blocksizebits(ksurf->color_format);
+ err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height,
+ block_bits, block_bits, stride, handle, &fb->buffer_id);
+ if (err) {
+ fb->buffer_id = 0;
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static boolean
+kms_surface_flush_frontbuffer(struct native_surface *nsurf)
+{
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ struct kms_display *kdpy = ksurf->kdpy;
+
+ /* pbuffer is private */
+ if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ if (ksurf->front_fb.is_passive)
+ drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0);
+#endif
+
+ return TRUE;
+}
+
+static boolean
+kms_surface_swap_buffers(struct native_surface *nsurf)
+{
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ struct kms_crtc *kcrtc = &ksurf->current_crtc;
+ struct kms_display *kdpy = ksurf->kdpy;
+ struct kms_framebuffer tmp_fb;
+ struct pipe_texture *tmp_texture;
+ int err;
+
+ /* pbuffer is private */
+ if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ if (!ksurf->back_fb.buffer_id) {
+ if (!kms_surface_init_framebuffers(&ksurf->base, TRUE))
+ return FALSE;
+ }
+
+ if (ksurf->is_shown && kcrtc->crtc) {
+ err = drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
+ ksurf->back_fb.buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
+ kcrtc->connectors, kcrtc->num_connectors, &kcrtc->crtc->mode);
+ if (err)
+ return FALSE;
+ }
+
+ /* swap the buffers */
+ tmp_fb = ksurf->front_fb;
+ ksurf->front_fb = ksurf->back_fb;
+ ksurf->back_fb = tmp_fb;
+
+ tmp_texture = ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT];
+ ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT] =
+ ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT];
+ ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT] = tmp_texture;
+
+ /* the front/back textures are swapped */
+ ksurf->sequence_number++;
+
+ return TRUE;
+}
+
+static void
+kms_surface_wait(struct native_surface *nsurf)
+{
+ /* no-op */
+}
+
+static void
+kms_surface_destroy(struct native_surface *nsurf)
+{
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ int i;
+
+ if (ksurf->current_crtc.crtc)
+ drmModeFreeCrtc(ksurf->current_crtc.crtc);
+
+ if (ksurf->front_fb.buffer_id)
+ drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id);
+ pipe_texture_reference(&ksurf->front_fb.texture, NULL);
+
+ if (ksurf->back_fb.buffer_id)
+ drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id);
+ pipe_texture_reference(&ksurf->back_fb.texture, NULL);
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct pipe_texture *ptex = ksurf->textures[i];
+ pipe_texture_reference(&ptex, NULL);
+ }
+
+ free(ksurf);
+}
+
+static struct kms_surface *
+kms_display_create_surface(struct native_display *ndpy,
+ enum kms_surface_type type,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct kms_config *kconf = kms_config(nconf);
+ struct kms_surface *ksurf;
+
+ ksurf = CALLOC_STRUCT(kms_surface);
+ if (!ksurf)
+ return NULL;
+
+ ksurf->kdpy = kdpy;
+ ksurf->type = type;
+ ksurf->color_format = kconf->base.color_format;
+ ksurf->width = width;
+ ksurf->height = height;
+
+ ksurf->base.destroy = kms_surface_destroy;
+ ksurf->base.swap_buffers = kms_surface_swap_buffers;
+ ksurf->base.flush_frontbuffer = kms_surface_flush_frontbuffer;
+ ksurf->base.validate = kms_surface_validate;
+ ksurf->base.wait = kms_surface_wait;
+
+ return ksurf;
+}
+
+/**
+ * Choose a CRTC that supports all given connectors.
+ */
+static uint32_t
+kms_display_choose_crtc(struct native_display *ndpy,
+ uint32_t *connectors, int num_connectors)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ int idx;
+
+ for (idx = 0; idx < kdpy->resources->count_crtcs; idx++) {
+ boolean found_crtc = TRUE;
+ int i, j;
+
+ for (i = 0; i < num_connectors; i++) {
+ drmModeConnectorPtr connector;
+ int encoder_idx = -1;
+
+ connector = drmModeGetConnector(kdpy->fd, connectors[i]);
+ if (!connector) {
+ found_crtc = FALSE;
+ break;
+ }
+
+ /* find an encoder the CRTC supports */
+ for (j = 0; j < connector->count_encoders; j++) {
+ drmModeEncoderPtr encoder =
+ drmModeGetEncoder(kdpy->fd, connector->encoders[j]);
+ if (encoder->possible_crtcs & (1 << idx)) {
+ encoder_idx = j;
+ break;
+ }
+ drmModeFreeEncoder(encoder);
+ }
+
+ drmModeFreeConnector(connector);
+ if (encoder_idx < 0) {
+ found_crtc = FALSE;
+ break;
+ }
+ }
+
+ if (found_crtc)
+ break;
+ }
+
+ if (idx >= kdpy->resources->count_crtcs) {
+ _eglLog(_EGL_WARNING,
+ "failed to find a CRTC that supports the given %d connectors",
+ num_connectors);
+ return 0;
+ }
+
+ return kdpy->resources->crtcs[idx];
+}
+
+/**
+ * Remember the original CRTC status and set the CRTC
+ */
+static boolean
+kms_display_set_crtc(struct native_display *ndpy, int crtc_idx,
+ uint32_t buffer_id, uint32_t x, uint32_t y,
+ uint32_t *connectors, int num_connectors,
+ drmModeModeInfoPtr mode)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct kms_crtc *kcrtc = &kdpy->saved_crtcs[crtc_idx];
+ uint32_t crtc_id;
+ int err;
+
+ if (kcrtc->crtc) {
+ crtc_id = kcrtc->crtc->crtc_id;
+ }
+ else {
+ int count = 0, i;
+
+ /*
+ * Choose the CRTC once. It could be more dynamic, but let's keep it
+ * simple for now.
+ */
+ crtc_id = kms_display_choose_crtc(&kdpy->base,
+ connectors, num_connectors);
+
+ /* save the original CRTC status */
+ kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
+ if (!kcrtc->crtc)
+ return FALSE;
+
+ for (i = 0; i < kdpy->num_connectors; i++) {
+ struct kms_connector *kconn = &kdpy->connectors[i];
+ drmModeConnectorPtr connector = kconn->connector;
+ drmModeEncoderPtr encoder;
+
+ encoder = drmModeGetEncoder(kdpy->fd, connector->encoder_id);
+ if (encoder) {
+ if (encoder->crtc_id == crtc_id) {
+ kcrtc->connectors[count++] = connector->connector_id;
+ if (count >= Elements(kcrtc->connectors))
+ break;
+ }
+ drmModeFreeEncoder(encoder);
+ }
+ }
+
+ kcrtc->num_connectors = count;
+ }
+
+ err = drmModeSetCrtc(kdpy->fd, crtc_id, buffer_id, x, y,
+ connectors, num_connectors, mode);
+ if (err) {
+ drmModeFreeCrtc(kcrtc->crtc);
+ kcrtc->crtc = NULL;
+ kcrtc->num_connectors = 0;
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static boolean
+kms_display_program(struct native_display *ndpy, int crtc_idx,
+ struct native_surface *nsurf, uint x, uint y,
+ const struct native_connector **nconns, int num_nconns,
+ const struct native_mode *nmode)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct kms_surface *ksurf = kms_surface(nsurf);
+ const struct kms_mode *kmode = kms_mode(nmode);
+ uint32_t connector_ids[32];
+ uint32_t buffer_id;
+ drmModeModeInfo mode_tmp, *mode;
+ int i;
+
+ if (num_nconns > Elements(connector_ids)) {
+ _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
+ num_nconns = Elements(connector_ids);
+ }
+
+ if (ksurf) {
+ if (!kms_surface_init_framebuffers(&ksurf->base, FALSE))
+ return FALSE;
+
+ buffer_id = ksurf->front_fb.buffer_id;
+ /* the mode argument of drmModeSetCrtc is not constified */
+ mode_tmp = kmode->mode;
+ mode = &mode_tmp;
+ }
+ else {
+ /* disable the CRTC */
+ buffer_id = 0;
+ mode = NULL;
+ num_nconns = 0;
+ }
+
+ for (i = 0; i < num_nconns; i++) {
+ struct kms_connector *kconn = kms_connector(nconns[i]);
+ connector_ids[i] = kconn->connector->connector_id;
+ }
+
+ if (!kms_display_set_crtc(&kdpy->base, crtc_idx, buffer_id, x, y,
+ connector_ids, num_nconns, mode)) {
+ _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
+
+ return FALSE;
+ }
+
+ if (kdpy->shown_surfaces[crtc_idx])
+ kdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
+ kdpy->shown_surfaces[crtc_idx] = ksurf;
+
+ /* remember the settings for buffer swapping */
+ if (ksurf) {
+ uint32_t crtc_id = kdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
+ struct kms_crtc *kcrtc = &ksurf->current_crtc;
+
+ if (kcrtc->crtc)
+ drmModeFreeCrtc(kcrtc->crtc);
+ kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
+
+ assert(num_nconns < Elements(kcrtc->connectors));
+ memcpy(kcrtc->connectors, connector_ids,
+ sizeof(*connector_ids) * num_nconns);
+ kcrtc->num_connectors = num_nconns;
+
+ ksurf->is_shown = TRUE;
+ }
+
+ return TRUE;
+}
+
+static const struct native_mode **
+kms_display_get_modes(struct native_display *ndpy,
+ const struct native_connector *nconn,
+ int *num_modes)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct kms_connector *kconn = kms_connector(nconn);
+ const struct native_mode **nmodes_return;
+ int count, i;
+
+ /* delete old data */
+ if (kconn->connector) {
+ drmModeFreeConnector(kconn->connector);
+ free(kconn->kms_modes);
+
+ kconn->connector = NULL;
+ kconn->kms_modes = NULL;
+ kconn->num_modes = 0;
+ }
+
+ /* detect again */
+ kconn->connector = drmModeGetConnector(kdpy->fd, kconn->connector_id);
+ if (!kconn->connector)
+ return NULL;
+
+ count = kconn->connector->count_modes;
+ kconn->kms_modes = calloc(count, sizeof(*kconn->kms_modes));
+ if (!kconn->kms_modes) {
+ drmModeFreeConnector(kconn->connector);
+ kconn->connector = NULL;
+
+ return NULL;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct kms_mode *kmode = &kconn->kms_modes[i];
+ drmModeModeInfoPtr mode = &kconn->connector->modes[i];
+
+ kmode->mode = *mode;
+
+ kmode->base.desc = kmode->mode.name;
+ kmode->base.width = kmode->mode.hdisplay;
+ kmode->base.height = kmode->mode.vdisplay;
+ kmode->base.refresh_rate = kmode->mode.vrefresh / 1000;
+ }
+
+ nmodes_return = malloc(count * sizeof(*nmodes_return));
+ if (nmodes_return) {
+ for (i = 0; i < count; i++)
+ nmodes_return[i] = &kconn->kms_modes[i].base;
+ if (num_modes)
+ *num_modes = count;
+ }
+
+ return nmodes_return;
+}
+
+static const struct native_connector **
+kms_display_get_connectors(struct native_display *ndpy, int *num_connectors,
+ int *num_crtc)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ const struct native_connector **connectors;
+ int i;
+
+ if (!kdpy->connectors) {
+ kdpy->connectors =
+ calloc(kdpy->resources->count_connectors, sizeof(*kdpy->connectors));
+ if (!kdpy->connectors)
+ return NULL;
+
+ for (i = 0; i < kdpy->resources->count_connectors; i++) {
+ struct kms_connector *kconn = &kdpy->connectors[i];
+
+ kconn->connector_id = kdpy->resources->connectors[i];
+ /* kconn->connector is allocated when the modes are asked */
+ }
+
+ kdpy->num_connectors = kdpy->resources->count_connectors;
+ }
+
+ connectors = malloc(kdpy->num_connectors * sizeof(*connectors));
+ if (connectors) {
+ for (i = 0; i < kdpy->num_connectors; i++)
+ connectors[i] = &kdpy->connectors[i].base;
+ if (num_connectors)
+ *num_connectors = kdpy->num_connectors;
+ }
+
+ if (num_crtc)
+ *num_crtc = kdpy->resources->count_crtcs;
+
+ return connectors;
+}
+
+static struct native_surface *
+kms_display_create_scanout_surface(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct kms_surface *ksurf;
+
+ ksurf = kms_display_create_surface(ndpy,
+ KMS_SURFACE_TYPE_SCANOUT, nconf, width, height);
+ return &ksurf->base;
+}
+
+static struct native_surface *
+kms_display_create_pbuffer_surface(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct kms_surface *ksurf;
+
+ ksurf = kms_display_create_surface(ndpy,
+ KMS_SURFACE_TYPE_PBUFFER, nconf, width, height);
+ return &ksurf->base;
+}
+
+static struct pipe_context *
+kms_display_create_context(struct native_display *ndpy, void *context_private)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct pipe_context *pctx;
+
+ pctx = kdpy->api->create_context(kdpy->api, kdpy->base.screen);
+ if (pctx)
+ pctx->priv = context_private;
+ return pctx;
+}
+
+static boolean
+kms_display_is_format_supported(struct native_display *ndpy,
+ enum pipe_format fmt, boolean is_color)
+{
+ return ndpy->screen->is_format_supported(ndpy->screen,
+ fmt, PIPE_TEXTURE_2D,
+ (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET :
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+}
+
+static const struct native_config **
+kms_display_get_configs(struct native_display *ndpy, int *num_configs)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ const struct native_config **configs;
+
+ /* first time */
+ if (!kdpy->config) {
+ struct native_config *nconf;
+ enum pipe_format format;
+
+ kdpy->config = calloc(1, sizeof(*kdpy->config));
+ if (!kdpy->config)
+ return NULL;
+
+ nconf = &kdpy->config->base;
+
+ /* always double-buffered */
+ nconf->mode.doubleBufferMode = TRUE;
+
+ format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) {
+ format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ if (!kms_display_is_format_supported(&kdpy->base, format, TRUE))
+ format = PIPE_FORMAT_NONE;
+ }
+ if (format == PIPE_FORMAT_NONE)
+ return NULL;
+
+ nconf->color_format = format;
+ nconf->mode.redBits = 8;
+ nconf->mode.greenBits = 8;
+ nconf->mode.blueBits = 8;
+ nconf->mode.alphaBits = 8;
+ nconf->mode.rgbBits = 32;
+
+ format = PIPE_FORMAT_S8Z24_UNORM;
+ if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) {
+ format = PIPE_FORMAT_Z24S8_UNORM;
+ if (!kms_display_is_format_supported(&kdpy->base, format, FALSE))
+ format = PIPE_FORMAT_NONE;
+ }
+ if (format != PIPE_FORMAT_NONE) {
+ nconf->depth_format = format;
+ nconf->stencil_format = format;
+
+ nconf->mode.depthBits = 24;
+ nconf->mode.stencilBits = 8;
+ nconf->mode.haveDepthBuffer = TRUE;
+ nconf->mode.haveStencilBuffer = TRUE;
+ }
+
+ nconf->scanout_bit = TRUE;
+ nconf->mode.drawableType = GLX_PBUFFER_BIT;
+ nconf->mode.swapMethod = GLX_SWAP_EXCHANGE_OML;
+
+ nconf->mode.visualID = 0;
+ nconf->mode.visualType = EGL_NONE;
+
+ nconf->mode.renderType = GLX_RGBA_BIT;
+ nconf->mode.rgbMode = TRUE;
+ nconf->mode.xRenderable = FALSE;
+ }
+
+ configs = malloc(sizeof(*configs));
+ if (configs) {
+ configs[0] = &kdpy->config->base;
+ if (num_configs)
+ *num_configs = 1;
+ }
+
+ return configs;
+}
+
+static void
+kms_display_destroy(struct native_display *ndpy)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ int i;
+
+ if (kdpy->config)
+ free(kdpy->config);
+
+ if (kdpy->connectors) {
+ for (i = 0; i < kdpy->num_connectors; i++) {
+ struct kms_connector *kconn = &kdpy->connectors[i];
+ if (kconn->connector) {
+ drmModeFreeConnector(kconn->connector);
+ free(kconn->kms_modes);
+ }
+ }
+ free(kdpy->connectors);
+ }
+
+ if (kdpy->shown_surfaces)
+ free(kdpy->shown_surfaces);
+
+ if (kdpy->saved_crtcs) {
+ for (i = 0; i < kdpy->resources->count_crtcs; i++) {
+ struct kms_crtc *kcrtc = &kdpy->saved_crtcs[i];
+
+ if (kcrtc->crtc) {
+ /* restore crtc */
+ drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
+ kcrtc->crtc->buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
+ kcrtc->connectors, kcrtc->num_connectors,
+ &kcrtc->crtc->mode);
+
+ drmModeFreeCrtc(kcrtc->crtc);
+ }
+ }
+ free(kdpy->saved_crtcs);
+ }
+
+ if (kdpy->resources)
+ drmModeFreeResources(kdpy->resources);
+
+ if (kdpy->base.screen)
+ kdpy->base.screen->destroy(kdpy->base.screen);
+
+ if (kdpy->fd >= 0)
+ drmClose(kdpy->fd);
+
+ if (kdpy->api)
+ kdpy->api->destroy(kdpy->api);
+ free(kdpy);
+}
+
+/**
+ * Initialize KMS and pipe screen.
+ */
+static boolean
+kms_display_init_screen(struct native_display *ndpy)
+{
+ struct kms_display *kdpy = kms_display(ndpy);
+ struct drm_create_screen_arg arg;
+ int fd;
+
+ fd = drmOpen(kdpy->api->name, NULL);
+ if (fd < 0) {
+ _eglLog(_EGL_WARNING, "failed to open DRM device");
+ return FALSE;
+ }
+
+#if 0
+ if (drmSetMaster(fd)) {
+ _eglLog(_EGL_WARNING, "failed to become DRM master");
+ return FALSE;
+ }
+#endif
+
+ memset(&arg, 0, sizeof(arg));
+ arg.mode = DRM_CREATE_NORMAL;
+ kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, &arg);
+ if (!kdpy->base.screen) {
+ _eglLog(_EGL_WARNING, "failed to create DRM screen");
+ drmClose(fd);
+ return FALSE;
+ }
+
+ kdpy->fd = fd;
+
+ return TRUE;
+}
+
+static struct native_display_modeset kms_display_modeset = {
+ .get_connectors = kms_display_get_connectors,
+ .get_modes = kms_display_get_modes,
+ .create_scanout_surface = kms_display_create_scanout_surface,
+ .program = kms_display_program
+};
+
+static struct native_display *
+kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
+{
+ struct kms_display *kdpy;
+
+ kdpy = CALLOC_STRUCT(kms_display);
+ if (!kdpy)
+ return NULL;
+
+ kdpy->api = api;
+ if (!kdpy->api) {
+ _eglLog(_EGL_WARNING, "failed to create DRM API");
+ free(kdpy);
+ return NULL;
+ }
+
+ kdpy->fd = -1;
+ if (!kms_display_init_screen(&kdpy->base)) {
+ kms_display_destroy(&kdpy->base);
+ return NULL;
+ }
+
+ /* resources are fixed, unlike crtc, connector, or encoder */
+ kdpy->resources = drmModeGetResources(kdpy->fd);
+ if (!kdpy->resources) {
+ kms_display_destroy(&kdpy->base);
+ return NULL;
+ }
+
+ kdpy->saved_crtcs =
+ calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs));
+ if (!kdpy->saved_crtcs) {
+ kms_display_destroy(&kdpy->base);
+ return NULL;
+ }
+
+ kdpy->shown_surfaces =
+ calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces));
+ if (!kdpy->shown_surfaces) {
+ kms_display_destroy(&kdpy->base);
+ return NULL;
+ }
+
+ kdpy->base.destroy = kms_display_destroy;
+ kdpy->base.get_configs = kms_display_get_configs;
+ kdpy->base.create_context = kms_display_create_context;
+ kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface;
+
+ kdpy->base.modeset = &kms_display_modeset;
+
+ return &kdpy->base;
+}
+
+/* the api is destroyed with the native display */
+static struct drm_api *drm_api;
+
+const char *
+native_get_name(void)
+{
+ static char kms_name[32];
+
+ if (!drm_api)
+ drm_api = drm_api_create();
+
+ if (drm_api)
+ snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name);
+ else
+ snprintf(kms_name, sizeof(kms_name), "KMS");
+
+ return kms_name;
+}
+
+struct native_display *
+native_create_display(EGLNativeDisplayType dpy)
+{
+ struct native_display *ndpy = NULL;
+
+ if (!drm_api)
+ drm_api = drm_api_create();
+
+ if (drm_api)
+ ndpy = kms_create_display(dpy, drm_api);
+
+ return ndpy;
+}
diff --git a/src/gallium/state_trackers/egl_g3d/kms/native_kms.h b/src/gallium/state_trackers/egl_g3d/kms/native_kms.h
new file mode 100644
index 00000000000..095186e3cf3
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/kms/native_kms.h
@@ -0,0 +1,139 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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 _NATIVE_KMS_H_
+#define _NATIVE_KMS_H_
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "pipe/p_compiler.h"
+#include "util/u_format.h"
+#include "pipe/p_state.h"
+#include "state_tracker/drm_api.h"
+
+#include "common/native.h"
+
+enum kms_surface_type {
+ KMS_SURFACE_TYPE_PBUFFER,
+ KMS_SURFACE_TYPE_SCANOUT
+};
+
+struct kms_config;
+struct kms_connector;
+struct kms_mode;
+
+struct kms_crtc {
+ drmModeCrtcPtr crtc;
+ uint32_t connectors[32];
+ int num_connectors;
+};
+
+struct kms_display {
+ struct native_display base;
+
+ int fd;
+ struct drm_api *api;
+ drmModeResPtr resources;
+ struct kms_config *config;
+
+ struct kms_connector *connectors;
+ int num_connectors;
+
+ struct kms_surface **shown_surfaces;
+ /* save the original settings of the CRTCs */
+ struct kms_crtc *saved_crtcs;
+};
+
+struct kms_framebuffer {
+ struct pipe_texture *texture;
+ boolean is_passive;
+
+ uint32_t buffer_id;
+};
+
+struct kms_surface {
+ struct native_surface base;
+ enum kms_surface_type type;
+ enum pipe_format color_format;
+ struct kms_display *kdpy;
+ int width, height;
+
+ struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
+ unsigned int sequence_number;
+ struct kms_framebuffer front_fb, back_fb;
+
+ boolean is_shown;
+ struct kms_crtc current_crtc;
+};
+
+struct kms_config {
+ struct native_config base;
+};
+
+struct kms_connector {
+ struct native_connector base;
+
+ uint32_t connector_id;
+ drmModeConnectorPtr connector;
+ struct kms_mode *kms_modes;
+ int num_modes;
+};
+
+struct kms_mode {
+ struct native_mode base;
+ drmModeModeInfo mode;
+};
+
+static INLINE struct kms_display *
+kms_display(const struct native_display *ndpy)
+{
+ return (struct kms_display *) ndpy;
+}
+
+static INLINE struct kms_surface *
+kms_surface(const struct native_surface *nsurf)
+{
+ return (struct kms_surface *) nsurf;
+}
+
+static INLINE struct kms_config *
+kms_config(const struct native_config *nconf)
+{
+ return (struct kms_config *) nconf;
+}
+
+static INLINE struct kms_connector *
+kms_connector(const struct native_connector *nconn)
+{
+ return (struct kms_connector *) nconn;
+}
+
+static INLINE struct kms_mode *
+kms_mode(const struct native_mode *nmode)
+{
+ return (struct kms_mode *) nmode;
+}
+
+#endif /* _NATIVE_KMS_H_ */
diff --git a/src/gallium/state_trackers/egl_g3d/x11/glxinit.c b/src/gallium/state_trackers/egl_g3d/x11/glxinit.c
new file mode 100644
index 00000000000..c955a908b93
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/x11/glxinit.c
@@ -0,0 +1,573 @@
+/**
+ * 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
new file mode 100644
index 00000000000..515a8252220
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/x11/glxinit.h
@@ -0,0 +1,14 @@
+#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/egl_g3d/x11/native_dri2.c b/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c
new file mode 100644
index 00000000000..f497d8c1c77
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c
@@ -0,0 +1,690 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "pipe/p_compiler.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "state_tracker/drm_api.h"
+#include "egllog.h"
+
+#include "native_x11.h"
+#include "x11_screen.h"
+
+enum dri2_surface_type {
+ DRI2_SURFACE_TYPE_WINDOW,
+ DRI2_SURFACE_TYPE_PIXMAP,
+ DRI2_SURFACE_TYPE_PBUFFER
+};
+
+struct dri2_display {
+ struct native_display base;
+ Display *dpy;
+ boolean own_dpy;
+
+ struct drm_api *api;
+ struct x11_screen *xscr;
+ int xscr_number;
+
+ struct dri2_config *configs;
+ int num_configs;
+};
+
+struct dri2_surface {
+ struct native_surface base;
+ Drawable drawable;
+ enum dri2_surface_type type;
+ enum pipe_format color_format;
+ struct dri2_display *dri2dpy;
+
+ struct pipe_texture *pbuffer_textures[NUM_NATIVE_ATTACHMENTS];
+ boolean have_back, have_fake;
+ int width, height;
+ unsigned int sequence_number;
+};
+
+struct dri2_config {
+ struct native_config base;
+};
+
+static INLINE struct dri2_display *
+dri2_display(const struct native_display *ndpy)
+{
+ return (struct dri2_display *) ndpy;
+}
+
+static INLINE struct dri2_surface *
+dri2_surface(const struct native_surface *nsurf)
+{
+ return (struct dri2_surface *) nsurf;
+}
+
+static INLINE struct dri2_config *
+dri2_config(const struct native_config *nconf)
+{
+ return (struct dri2_config *) nconf;
+}
+
+static boolean
+dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ /* pbuffer is private */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ /* copy to real front buffer */
+ if (dri2surf->have_fake)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+
+ return TRUE;
+}
+
+static boolean
+dri2_surface_swap_buffers(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ /* pbuffer is private */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ /* copy to front buffer */
+ if (dri2surf->have_back)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferBackLeft, DRI2BufferFrontLeft);
+
+ /* and update fake front buffer */
+ if (dri2surf->have_fake)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+
+ return TRUE;
+}
+
+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)
+{
+ 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;
+
+ if (num_natts) {
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.last_level = 0;
+ templ.width0 = dri2surf->width;
+ templ.height0 = dri2surf->height;
+ templ.depth0 = 1;
+ templ.format = dri2surf->color_format;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+
+ if (textures)
+ memset(textures, 0, sizeof(*textures) * num_natts);
+ }
+
+ /* 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];
+
+ if (!ptex) {
+ ptex = screen->texture_create(screen, &templ);
+ dri2surf->pbuffer_textures[natt] = ptex;
+ }
+
+ if (textures)
+ pipe_texture_reference(&textures[i], ptex);
+ }
+
+ if (seq_num)
+ *seq_num = dri2surf->sequence_number;
+ if (width)
+ *width = dri2surf->width;
+ if (height)
+ *height = dri2surf->height;
+
+ 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;
+
+ 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[i] = dri2att;
+ texture_indices[natts[i]] = i;
+ }
+
+ dri2surf->have_back = FALSE;
+ dri2surf->have_fake = FALSE;
+
+ /* remember old geometry */
+ templ.width0 = dri2surf->width;
+ templ.height0 = dri2surf->height;
+
+ xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
+ &dri2surf->width, &dri2surf->height,
+ dri2atts, FALSE, num_ins, &num_outs);
+ if (!xbufs)
+ return FALSE;
+
+ if (templ.width0 != dri2surf->width || templ.height0 != dri2surf->height) {
+ /* are there cases where the buffers change and the geometry doesn't? */
+ dri2surf->sequence_number++;
+
+ templ.width0 = dri2surf->width;
+ templ.height0 = dri2surf->height;
+ }
+
+ for (i = 0; i < num_outs; i++) {
+ struct x11_drawable_buffer *xbuf = &xbufs[i];
+ const char *desc;
+ enum native_attachment natt;
+
+ switch (xbuf->attachment) {
+ case DRI2BufferFrontLeft:
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ desc = "DRI2 Front Buffer";
+ break;
+ case DRI2BufferFakeFrontLeft:
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ desc = "DRI2 Fake Front Buffer";
+ dri2surf->have_fake = TRUE;
+ break;
+ case DRI2BufferBackLeft:
+ natt = NATIVE_ATTACHMENT_BACK_LEFT;
+ desc = "DRI2 Back Buffer";
+ dri2surf->have_back = TRUE;
+ break;
+ default:
+ desc = NULL;
+ break;
+ }
+
+ if (!desc || texture_indices[natt] < 0 ||
+ (textures && textures[texture_indices[natt]])) {
+ if (!desc)
+ _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
+ else if (texture_indices[natt] < 0)
+ _eglLog(_EGL_WARNING, "unexpected buffer %d", xbuf->attachment);
+ else if (textures && textures[texture_indices[natt]])
+ _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
+ continue;
+ }
+
+ if (textures) {
+ struct pipe_texture *ptex =
+ dri2dpy->api->texture_from_shared_handle(dri2dpy->api,
+ dri2dpy->base.screen, &templ,
+ desc, xbuf->pitch, xbuf->name);
+ if (ptex) {
+ /* the caller owns the textures */
+ textures[texture_indices[natt]] = ptex;
+ }
+ }
+ }
+
+ free(xbufs);
+
+ if (seq_num)
+ *seq_num = dri2surf->sequence_number;
+ if (width)
+ *width = dri2surf->width;
+ if (height)
+ *height = dri2surf->height;
+
+ return TRUE;
+}
+
+static void
+dri2_surface_wait(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ if (dri2surf->have_fake) {
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+ }
+}
+
+static void
+dri2_surface_destroy(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ int i;
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct pipe_texture *ptex = dri2surf->pbuffer_textures[i];
+ pipe_texture_reference(&ptex, NULL);
+ }
+
+ if (dri2surf->drawable)
+ x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
+ dri2surf->drawable, FALSE);
+ free(dri2surf);
+}
+
+static struct dri2_surface *
+dri2_display_create_surface(struct native_display *ndpy,
+ enum dri2_surface_type type,
+ Drawable drawable,
+ const struct native_config *nconf)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ struct dri2_config *dri2conf = dri2_config(nconf);
+ struct dri2_surface *dri2surf;
+
+ dri2surf = CALLOC_STRUCT(dri2_surface);
+ if (!dri2surf)
+ return NULL;
+
+ if (drawable)
+ x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
+
+ dri2surf->dri2dpy = dri2dpy;
+ dri2surf->type = type;
+ dri2surf->drawable = drawable;
+ dri2surf->color_format = dri2conf->base.color_format;
+
+ dri2surf->base.destroy = dri2_surface_destroy;
+ dri2surf->base.swap_buffers = dri2_surface_swap_buffers;
+ dri2surf->base.flush_frontbuffer = dri2_surface_flush_frontbuffer;
+ dri2surf->base.validate = dri2_surface_validate;
+ dri2surf->base.wait = dri2_surface_wait;
+
+ return dri2surf;
+}
+
+static struct native_surface *
+dri2_display_create_window_surface(struct native_display *ndpy,
+ EGLNativeWindowType win,
+ const struct native_config *nconf)
+{
+ struct dri2_surface *dri2surf;
+
+ dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_WINDOW,
+ (Drawable) win, nconf);
+ return (dri2surf) ? &dri2surf->base : NULL;
+}
+
+static struct native_surface *
+dri2_display_create_pixmap_surface(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf)
+{
+ struct dri2_surface *dri2surf;
+
+ dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PIXMAP,
+ (Drawable) pix, nconf);
+ return (dri2surf) ? &dri2surf->base : NULL;
+}
+
+static struct native_surface *
+dri2_display_create_pbuffer_surface(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct dri2_surface *dri2surf;
+
+ dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PBUFFER,
+ (Drawable) None, nconf);
+ if (dri2surf) {
+ dri2surf->width = width;
+ dri2surf->height = height;
+ }
+ return (dri2surf) ? &dri2surf->base : NULL;
+}
+
+static struct pipe_context *
+dri2_display_create_context(struct native_display *ndpy, void *context_private)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ struct pipe_context *pctx;
+
+ pctx = dri2dpy->api->create_context(dri2dpy->api, dri2dpy->base.screen);
+ if (pctx)
+ pctx->priv = context_private;
+ return pctx;
+}
+
+static int
+choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
+{
+ int count = 0;
+
+ switch (mode->rgbBits) {
+ case 32:
+ formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
+ formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
+ break;
+ case 24:
+ formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
+ formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
+ formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
+ formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
+ break;
+ case 16:
+ formats[count++] = PIPE_FORMAT_R5G6B5_UNORM;
+ break;
+ default:
+ break;
+ }
+
+ return count;
+}
+
+static int
+choose_depth_stencil_format(const __GLcontextModes *mode,
+ enum pipe_format formats[32])
+{
+ int count = 0;
+
+ switch (mode->depthBits) {
+ case 32:
+ formats[count++] = PIPE_FORMAT_Z32_UNORM;
+ break;
+ case 24:
+ if (mode->stencilBits) {
+ formats[count++] = PIPE_FORMAT_S8Z24_UNORM;
+ formats[count++] = PIPE_FORMAT_Z24S8_UNORM;
+ }
+ else {
+ formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
+ formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
+ }
+ break;
+ case 16:
+ formats[count++] = PIPE_FORMAT_Z16_UNORM;
+ break;
+ default:
+ break;
+ }
+
+ return count;
+}
+
+static boolean
+is_format_supported(struct pipe_screen *screen,
+ enum pipe_format fmt, boolean is_color)
+{
+ return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D,
+ (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET :
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+}
+
+static boolean
+dri2_display_convert_config(struct native_display *ndpy,
+ const __GLcontextModes *mode,
+ struct native_config *nconf)
+{
+ enum pipe_format formats[32];
+ int num_formats, i;
+
+ if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
+ return FALSE;
+
+ /* skip single-buffered configs */
+ if (!mode->doubleBufferMode)
+ return FALSE;
+
+ nconf->mode = *mode;
+ nconf->mode.renderType = GLX_RGBA_BIT;
+ nconf->mode.rgbMode = TRUE;
+ /* pbuffer is allocated locally and is always supported */
+ nconf->mode.drawableType |= GLX_PBUFFER_BIT;
+ /* the swap method is always copy */
+ nconf->mode.swapMethod = GLX_SWAP_COPY_OML;
+
+ /* fix up */
+ nconf->mode.rgbBits =
+ nconf->mode.redBits + nconf->mode.greenBits +
+ nconf->mode.blueBits + nconf->mode.alphaBits;
+ if (!(nconf->mode.drawableType & GLX_WINDOW_BIT)) {
+ nconf->mode.visualID = 0;
+ nconf->mode.visualType = GLX_NONE;
+ }
+ if (!(nconf->mode.drawableType & GLX_PBUFFER_BIT)) {
+ nconf->mode.bindToTextureRgb = FALSE;
+ nconf->mode.bindToTextureRgba = FALSE;
+ }
+
+ nconf->color_format = PIPE_FORMAT_NONE;
+ nconf->depth_format = PIPE_FORMAT_NONE;
+ nconf->stencil_format = PIPE_FORMAT_NONE;
+
+ /* choose color format */
+ num_formats = choose_color_format(mode, formats);
+ for (i = 0; i < num_formats; i++) {
+ if (is_format_supported(ndpy->screen, formats[i], TRUE)) {
+ nconf->color_format = formats[i];
+ break;
+ }
+ }
+ if (nconf->color_format == PIPE_FORMAT_NONE)
+ return FALSE;
+
+ /* choose depth/stencil format */
+ num_formats = choose_depth_stencil_format(mode, formats);
+ for (i = 0; i < num_formats; i++) {
+ if (is_format_supported(ndpy->screen, formats[i], FALSE)) {
+ nconf->depth_format = formats[i];
+ nconf->stencil_format = formats[i];
+ break;
+ }
+ }
+ if ((nconf->mode.depthBits && nconf->depth_format == PIPE_FORMAT_NONE) ||
+ (nconf->mode.stencilBits && nconf->stencil_format == PIPE_FORMAT_NONE))
+ return FALSE;
+
+ return TRUE;
+}
+
+static const struct native_config **
+dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ const struct native_config **configs;
+ int i;
+
+ /* first time */
+ if (!dri2dpy->configs) {
+ const __GLcontextModes *modes;
+ int num_modes, count;
+
+ modes = x11_screen_get_glx_configs(dri2dpy->xscr);
+ if (!modes)
+ return NULL;
+ num_modes = x11_context_modes_count(modes);
+
+ dri2dpy->configs = calloc(num_modes, sizeof(*dri2dpy->configs));
+ if (!dri2dpy->configs)
+ return NULL;
+
+ count = 0;
+ for (i = 0; i < num_modes; i++) {
+ struct native_config *nconf = &dri2dpy->configs[count].base;
+ if (dri2_display_convert_config(&dri2dpy->base, modes, nconf))
+ count++;
+ modes = modes->next;
+ }
+
+ dri2dpy->num_configs = count;
+ }
+
+ configs = malloc(dri2dpy->num_configs * sizeof(*configs));
+ if (configs) {
+ for (i = 0; i < dri2dpy->num_configs; i++)
+ configs[i] = (const struct native_config *) &dri2dpy->configs[i];
+ if (num_configs)
+ *num_configs = dri2dpy->num_configs;
+ }
+
+ return configs;
+}
+
+static void
+dri2_display_destroy(struct native_display *ndpy)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+
+ if (dri2dpy->configs)
+ free(dri2dpy->configs);
+
+ if (dri2dpy->base.screen)
+ dri2dpy->base.screen->destroy(dri2dpy->base.screen);
+
+ if (dri2dpy->xscr)
+ x11_screen_destroy(dri2dpy->xscr);
+ if (dri2dpy->own_dpy)
+ XCloseDisplay(dri2dpy->dpy);
+ if (dri2dpy->api && dri2dpy->api->destroy)
+ dri2dpy->api->destroy(dri2dpy->api);
+ free(dri2dpy);
+}
+
+/**
+ * Initialize DRI2 and pipe screen.
+ */
+static boolean
+dri2_display_init_screen(struct native_display *ndpy)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ const char *driver = dri2dpy->api->name;
+ struct drm_create_screen_arg arg;
+ int fd;
+
+ if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
+ !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
+ _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
+ return FALSE;
+ }
+
+ fd = x11_screen_enable_dri2(dri2dpy->xscr, driver);
+ if (fd < 0)
+ return FALSE;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.mode = DRM_CREATE_NORMAL;
+ dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, &arg);
+ if (!dri2dpy->base.screen) {
+ _eglLog(_EGL_WARNING, "failed to create DRM screen");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+struct native_display *
+x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
+{
+ struct dri2_display *dri2dpy;
+
+ dri2dpy = CALLOC_STRUCT(dri2_display);
+ if (!dri2dpy)
+ return NULL;
+
+ dri2dpy->api = api;
+ if (!dri2dpy->api) {
+ _eglLog(_EGL_WARNING, "failed to create DRM API");
+ free(dri2dpy);
+ return NULL;
+ }
+
+ dri2dpy->dpy = dpy;
+ if (!dri2dpy->dpy) {
+ dri2dpy->dpy = XOpenDisplay(NULL);
+ if (!dri2dpy->dpy) {
+ dri2_display_destroy(&dri2dpy->base);
+ return NULL;
+ }
+ dri2dpy->own_dpy = TRUE;
+ }
+
+ dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
+ dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
+ if (!dri2dpy->xscr) {
+ dri2_display_destroy(&dri2dpy->base);
+ return NULL;
+ }
+
+ if (!dri2_display_init_screen(&dri2dpy->base)) {
+ dri2_display_destroy(&dri2dpy->base);
+ return NULL;
+ }
+
+ dri2dpy->base.destroy = dri2_display_destroy;
+ dri2dpy->base.get_configs = dri2_display_get_configs;
+ 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;
+ dri2dpy->base.create_pbuffer_surface = dri2_display_create_pbuffer_surface;
+
+ return &dri2dpy->base;
+}
diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_x11.c b/src/gallium/state_trackers/egl_g3d/x11/native_x11.c
new file mode 100644
index 00000000000..583ce3d3293
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/x11/native_x11.c
@@ -0,0 +1,72 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <string.h>
+#include "util/u_debug.h"
+#include "state_tracker/drm_api.h"
+#include "egllog.h"
+
+#include "native_x11.h"
+
+static struct drm_api *api;
+
+const char *
+native_get_name(void)
+{
+ static char x11_name[32];
+
+ if (!api)
+ api = drm_api_create();
+
+ if (api)
+ snprintf(x11_name, sizeof(x11_name), "X11/%s", api->name);
+ else
+ snprintf(x11_name, sizeof(x11_name), "X11");
+
+ return x11_name;
+}
+
+struct native_display *
+native_create_display(EGLNativeDisplayType dpy)
+{
+ struct native_display *ndpy = NULL;
+ boolean force_sw;
+
+ if (!api)
+ api = drm_api_create();
+
+ force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
+ if (api && !force_sw) {
+ ndpy = x11_create_dri2_display(dpy, api);
+ }
+
+ if (!ndpy) {
+ EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING;
+
+ _eglLog(level, "use software fallback");
+ ndpy = x11_create_ximage_display(dpy, TRUE);
+ }
+
+ return ndpy;
+}
diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_x11.h b/src/gallium/state_trackers/egl_g3d/x11/native_x11.h
new file mode 100644
index 00000000000..622ddac5df6
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/x11/native_x11.h
@@ -0,0 +1,37 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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 _NATIVE_X11_H_
+#define _NATIVE_X11_H_
+
+#include "state_tracker/drm_api.h"
+#include "common/native.h"
+
+struct native_display *
+x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm);
+
+struct native_display *
+x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api);
+
+#endif /* _NATIVE_X11_H_ */
diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c b/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c
new file mode 100644
index 00000000000..24a50df7a0a
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c
@@ -0,0 +1,676 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/XShm.h>
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "pipe/p_compiler.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "softpipe/sp_winsys.h"
+#include "egllog.h"
+
+#include "sw_winsys.h"
+#include "native_x11.h"
+#include "x11_screen.h"
+
+enum ximage_surface_type {
+ XIMAGE_SURFACE_TYPE_WINDOW,
+ XIMAGE_SURFACE_TYPE_PIXMAP,
+ XIMAGE_SURFACE_TYPE_PBUFFER
+};
+
+struct ximage_display {
+ struct native_display base;
+ Display *dpy;
+ boolean own_dpy;
+
+ struct x11_screen *xscr;
+ int xscr_number;
+
+ boolean use_xshm;
+
+ struct pipe_winsys *winsys;
+ struct ximage_config *configs;
+ int num_configs;
+};
+
+struct ximage_buffer {
+ XImage *ximage;
+
+ struct pipe_texture *texture;
+ struct pipe_transfer *transfer;
+ XShmSegmentInfo *shm_info;
+ boolean xshm_attached;
+};
+
+struct ximage_surface {
+ struct native_surface base;
+ Drawable drawable;
+ enum ximage_surface_type type;
+ enum pipe_format color_format;
+ XVisualInfo visual;
+ struct ximage_display *xdpy;
+
+ int width, height;
+ GC gc;
+
+ struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS];
+ unsigned int sequence_number;
+};
+
+struct ximage_config {
+ struct native_config base;
+ const XVisualInfo *visual;
+};
+
+static INLINE struct ximage_display *
+ximage_display(const struct native_display *ndpy)
+{
+ return (struct ximage_display *) ndpy;
+}
+
+static INLINE struct ximage_surface *
+ximage_surface(const struct native_surface *nsurf)
+{
+ return (struct ximage_surface *) nsurf;
+}
+
+static INLINE struct ximage_config *
+ximage_config(const struct native_config *nconf)
+{
+ return (struct ximage_config *) nconf;
+}
+
+static void
+ximage_surface_free_buffer(struct native_surface *nsurf,
+ enum native_attachment which)
+{
+ 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) {
+ if (xbuf->xshm_attached)
+ XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info);
+ if (xbuf->shm_info->shmaddr != (void *) -1)
+ shmdt(xbuf->shm_info->shmaddr);
+ if (xbuf->shm_info->shmid != -1)
+ shmctl(xbuf->shm_info->shmid, IPC_RMID, 0);
+
+ xbuf->shm_info->shmaddr = (void *) -1;
+ xbuf->shm_info->shmid = -1;
+ }
+}
+
+static boolean
+ximage_surface_alloc_buffer(struct native_surface *nsurf,
+ enum native_attachment which)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xbuf = &xsurf->buffers[which];
+ struct pipe_screen *screen = xsurf->xdpy->base.screen;
+ struct pipe_texture templ;
+
+ /* free old data */
+ if (xbuf->texture)
+ ximage_surface_free_buffer(&xsurf->base, which);
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = xsurf->color_format;
+ templ.width0 = xsurf->width;
+ templ.height0 = xsurf->height;
+ templ.depth0 = 1;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+
+ if (xbuf->shm_info) {
+ struct pipe_buffer *pbuf;
+ unsigned stride, size;
+ void *addr = NULL;
+
+ stride = util_format_get_stride(xsurf->color_format, xsurf->width);
+ /* alignment should depend on visual? */
+ stride = align(stride, 4);
+ size = stride * xsurf->height;
+
+ /* create and attach shm object */
+ xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755);
+ if (xbuf->shm_info->shmid != -1) {
+ xbuf->shm_info->shmaddr =
+ shmat(xbuf->shm_info->shmid, NULL, 0);
+ if (xbuf->shm_info->shmaddr != (void *) -1) {
+ if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) {
+ addr = xbuf->shm_info->shmaddr;
+ xbuf->xshm_attached = TRUE;
+ }
+ }
+ }
+
+ if (addr) {
+ pbuf = screen->user_buffer_create(screen, addr, size);
+ if (pbuf) {
+ xbuf->texture =
+ screen->texture_blanket(screen, &templ, &stride, pbuf);
+ pipe_buffer_reference(&pbuf, NULL);
+ }
+ }
+ }
+ else {
+ 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);
+
+ return (xbuf->texture != NULL);
+}
+
+static boolean
+ximage_surface_draw_buffer(struct native_surface *nsurf,
+ enum native_attachment which)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xbuf = &xsurf->buffers[which];
+ struct pipe_screen *screen = xsurf->xdpy->base.screen;
+
+ 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);
+
+ if (xbuf->shm_info)
+ XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc,
+ xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False);
+ else
+ XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc,
+ xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height);
+
+ xbuf->ximage->data = NULL;
+ screen->transfer_unmap(screen, xbuf->transfer);
+
+ XSync(xsurf->xdpy->dpy, FALSE);
+
+ return TRUE;
+}
+
+static boolean
+ximage_surface_flush_frontbuffer(struct native_surface *nsurf)
+{
+ return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
+}
+
+static boolean
+ximage_surface_swap_buffers(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xfront, *xback, xtmp;
+
+ xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT];
+ xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT];
+
+ /* draw the back buffer directly if there is no front buffer */
+ if (!xfront->texture)
+ return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT);
+
+ /* swap the buffers */
+ xtmp = *xfront;
+ *xfront = *xback;
+ *xback = xtmp;
+
+ /* the front/back textures are swapped */
+ xsurf->sequence_number++;
+
+ return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
+}
+
+static void
+ximage_surface_update_geometry(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ Status ok;
+ Window root;
+ int x, y;
+ unsigned int w, h, border, depth;
+
+ /* pbuffer has fixed geometry */
+ if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER)
+ return;
+
+ ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable,
+ &root, &x, &y, &w, &h, &border, &depth);
+ if (ok) {
+ xsurf->width = w;
+ xsurf->height = h;
+ }
+}
+
+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)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ boolean new_buffers = FALSE, error = FALSE;
+ unsigned i;
+
+ 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];
+
+ if (!xbuf)
+ continue;
+
+ /* reallocate the texture */
+ if (!xbuf->texture ||
+ xsurf->width != xbuf->texture->width0 ||
+ xsurf->height != xbuf->texture->height0) {
+ new_buffers = TRUE;
+ if (ximage_surface_alloc_buffer(&xsurf->base, natt)) {
+ /* 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;
+ }
+ }
+ }
+
+ /* 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)
+ pipe_texture_reference(&textures[i], xbuf->texture);
+ }
+
+ /* increase the sequence number so that caller knows */
+ if (new_buffers)
+ xsurf->sequence_number++;
+
+ if (seq_num)
+ *seq_num = xsurf->sequence_number;
+ if (width)
+ *width = xsurf->width;
+ if (height)
+ *height = xsurf->height;
+
+ return !error;
+}
+
+static void
+ximage_surface_wait(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ XSync(xsurf->xdpy->dpy, FALSE);
+ /* TODO XGetImage and update the front texture */
+}
+
+static void
+ximage_surface_destroy(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ int i;
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct ximage_buffer *xbuf = &xsurf->buffers[i];
+ ximage_surface_free_buffer(&xsurf->base, i);
+ /* xbuf->shm_info is owned by xbuf->ximage? */
+ if (xbuf->ximage) {
+ XDestroyImage(xbuf->ximage);
+ xbuf->ximage = NULL;
+ }
+ }
+
+ if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER)
+ XFreeGC(xsurf->xdpy->dpy, xsurf->gc);
+ free(xsurf);
+}
+
+static struct ximage_surface *
+ximage_display_create_surface(struct native_display *ndpy,
+ enum ximage_surface_type type,
+ Drawable drawable,
+ const struct native_config *nconf)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+ struct ximage_config *xconf = ximage_config(nconf);
+ struct ximage_surface *xsurf;
+ int i;
+
+ xsurf = CALLOC_STRUCT(ximage_surface);
+ if (!xsurf)
+ return NULL;
+
+ xsurf->xdpy = xdpy;
+ xsurf->type = type;
+ xsurf->color_format = xconf->base.color_format;
+ xsurf->drawable = drawable;
+
+ if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) {
+ xsurf->drawable = drawable;
+ xsurf->visual = *xconf->visual;
+
+ xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL);
+ if (!xsurf->gc) {
+ free(xsurf);
+ return NULL;
+ }
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct ximage_buffer *xbuf = &xsurf->buffers[i];
+
+ if (xdpy->use_xshm) {
+ xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info));
+ if (xbuf->shm_info) {
+ /* initialize shm info */
+ xbuf->shm_info->shmid = -1;
+ xbuf->shm_info->shmaddr = (void *) -1;
+ xbuf->shm_info->readOnly = TRUE;
+
+ xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy,
+ xsurf->visual.visual,
+ xsurf->visual.depth,
+ ZPixmap, NULL,
+ xbuf->shm_info,
+ 0, 0);
+ }
+ }
+ else {
+ xbuf->ximage = XCreateImage(xsurf->xdpy->dpy,
+ xsurf->visual.visual,
+ xsurf->visual.depth,
+ ZPixmap, 0, /* format, offset */
+ NULL, /* data */
+ 0, 0, /* size */
+ 8, /* bitmap_pad */
+ 0); /* bytes_per_line */
+ }
+
+ if (!xbuf->ximage) {
+ XFreeGC(xdpy->dpy, xsurf->gc);
+ free(xsurf);
+ return NULL;
+ }
+ }
+ }
+
+ xsurf->base.destroy = ximage_surface_destroy;
+ xsurf->base.swap_buffers = ximage_surface_swap_buffers;
+ xsurf->base.flush_frontbuffer = ximage_surface_flush_frontbuffer;
+ xsurf->base.validate = ximage_surface_validate;
+ xsurf->base.wait = ximage_surface_wait;
+
+ return xsurf;
+}
+
+static struct native_surface *
+ximage_display_create_window_surface(struct native_display *ndpy,
+ EGLNativeWindowType win,
+ const struct native_config *nconf)
+{
+ struct ximage_surface *xsurf;
+
+ xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_WINDOW,
+ (Drawable) win, nconf);
+ return (xsurf) ? &xsurf->base : NULL;
+}
+
+static struct native_surface *
+ximage_display_create_pixmap_surface(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf)
+{
+ struct ximage_surface *xsurf;
+
+ xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PIXMAP,
+ (Drawable) pix, nconf);
+ return (xsurf) ? &xsurf->base : NULL;
+}
+
+static struct native_surface *
+ximage_display_create_pbuffer_surface(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct ximage_surface *xsurf;
+
+ xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PBUFFER,
+ (Drawable) None, nconf);
+ if (xsurf) {
+ xsurf->width = width;
+ xsurf->height = height;
+ }
+ return (xsurf) ? &xsurf->base : NULL;
+}
+
+static struct pipe_context *
+ximage_display_create_context(struct native_display *ndpy,
+ void *context_private)
+{
+ struct pipe_context *pctx = softpipe_create(ndpy->screen);
+ if (pctx)
+ pctx->priv = context_private;
+ return pctx;
+}
+
+static enum pipe_format
+choose_format(const XVisualInfo *vinfo)
+{
+ enum pipe_format fmt;
+ /* TODO elaborate the formats */
+ switch (vinfo->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;
+}
+
+static const struct native_config **
+ximage_display_get_configs(struct native_display *ndpy, int *num_configs)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+ const struct native_config **configs;
+ int i;
+
+ /* first time */
+ if (!xdpy->configs) {
+ const XVisualInfo *visuals;
+ int num_visuals, count, j;
+
+ visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals);
+ if (!visuals)
+ return NULL;
+
+ /*
+ * Create two configs for each visual.
+ * One with depth/stencil buffer; one without
+ */
+ xdpy->configs = calloc(num_visuals * 2, sizeof(*xdpy->configs));
+ if (!xdpy->configs)
+ return NULL;
+
+ count = 0;
+ for (i = 0; i < num_visuals; i++) {
+ for (j = 0; j < 2; j++) {
+ struct ximage_config *xconf = &xdpy->configs[count];
+ __GLcontextModes *mode = &xconf->base.mode;
+
+ xconf->visual = &visuals[i];
+ xconf->base.color_format = choose_format(xconf->visual);
+ if (xconf->base.color_format == PIPE_FORMAT_NONE)
+ continue;
+
+ x11_screen_convert_visual(xdpy->xscr, xconf->visual, mode);
+ /* support double buffer mode */
+ mode->doubleBufferMode = TRUE;
+
+ xconf->base.depth_format = PIPE_FORMAT_NONE;
+ xconf->base.stencil_format = PIPE_FORMAT_NONE;
+ /* create the second config with depth/stencil buffer */
+ if (j == 1) {
+ xconf->base.depth_format = PIPE_FORMAT_S8Z24_UNORM;
+ xconf->base.stencil_format = PIPE_FORMAT_S8Z24_UNORM;
+ mode->depthBits = 24;
+ mode->stencilBits = 8;
+ mode->haveDepthBuffer = TRUE;
+ mode->haveStencilBuffer = TRUE;
+ }
+
+ mode->maxPbufferWidth = 4096;
+ mode->maxPbufferHeight = 4096;
+ mode->maxPbufferPixels = 4096 * 4096;
+ mode->drawableType =
+ GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
+ mode->swapMethod = GLX_SWAP_EXCHANGE_OML;
+
+ if (mode->alphaBits)
+ mode->bindToTextureRgba = TRUE;
+ else
+ mode->bindToTextureRgb = TRUE;
+
+ count++;
+ }
+ }
+
+ xdpy->num_configs = count;
+ }
+
+ configs = malloc(xdpy->num_configs * sizeof(*configs));
+ if (configs) {
+ for (i = 0; i < xdpy->num_configs; i++)
+ configs[i] = (const struct native_config *) &xdpy->configs[i];
+ if (num_configs)
+ *num_configs = xdpy->num_configs;
+ }
+ return configs;
+}
+
+static void
+ximage_display_destroy(struct native_display *ndpy)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+
+ if (xdpy->configs)
+ free(xdpy->configs);
+
+ xdpy->base.screen->destroy(xdpy->base.screen);
+ free(xdpy->winsys);
+
+ x11_screen_destroy(xdpy->xscr);
+ if (xdpy->own_dpy)
+ XCloseDisplay(xdpy->dpy);
+ free(xdpy);
+}
+
+struct native_display *
+x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
+{
+ struct ximage_display *xdpy;
+
+ xdpy = CALLOC_STRUCT(ximage_display);
+ if (!xdpy)
+ return NULL;
+
+ xdpy->dpy = dpy;
+ if (!xdpy->dpy) {
+ xdpy->dpy = XOpenDisplay(NULL);
+ if (!xdpy->dpy) {
+ free(xdpy);
+ return NULL;
+ }
+ xdpy->own_dpy = TRUE;
+ }
+
+ xdpy->xscr_number = DefaultScreen(xdpy->dpy);
+ xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number);
+ if (!xdpy->xscr) {
+ free(xdpy);
+ return NULL;
+ }
+
+ xdpy->use_xshm =
+ (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM));
+
+ xdpy->winsys = create_sw_winsys();
+ xdpy->base.screen = softpipe_create_screen(xdpy->winsys);
+
+ xdpy->base.destroy = ximage_display_destroy;
+
+ xdpy->base.get_configs = ximage_display_get_configs;
+ 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;
+ xdpy->base.create_pbuffer_surface = ximage_display_create_pbuffer_surface;
+
+ return &xdpy->base;
+}
diff --git a/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c b/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c
new file mode 100644
index 00000000000..6ee3ede38cb
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c
@@ -0,0 +1,231 @@
+/**************************************************************************
+ *
+ * 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/state_trackers/egl_g3d/x11/sw_winsys.h b/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.h
new file mode 100644
index 00000000000..f96c5a14b0a
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.h
@@ -0,0 +1,40 @@
+/**************************************************************************
+ *
+ * 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/state_trackers/egl_g3d/x11/x11_screen.c b/src/gallium/state_trackers/egl_g3d/x11/x11_screen.c
new file mode 100644
index 00000000000..1e98943242a
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/x11/x11_screen.c
@@ -0,0 +1,402 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/XShm.h>
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "xf86drm.h"
+#include "egllog.h"
+
+#include "x11_screen.h"
+#include "dri2.h"
+#include "glxinit.h"
+
+struct x11_screen {
+ Display *dpy;
+ int number;
+
+ __GLXdisplayPrivate *glx_dpy;
+
+ int dri_major, dri_minor;
+ char *dri_driver;
+ char *dri_device;
+ int dri_fd;
+
+ XVisualInfo *visuals;
+ int num_visuals;
+};
+
+
+/**
+ * Create a X11 screen.
+ */
+struct x11_screen *
+x11_screen_create(Display *dpy, int screen)
+{
+ struct x11_screen *xscr;
+
+ if (screen >= ScreenCount(dpy))
+ return NULL;
+
+ xscr = CALLOC_STRUCT(x11_screen);
+ if (xscr) {
+ xscr->dpy = dpy;
+ xscr->number = screen;
+
+ xscr->dri_major = -1;
+ xscr->dri_fd = -1;
+ }
+ return xscr;
+}
+
+/**
+ * Destroy a X11 screen.
+ */
+void
+x11_screen_destroy(struct x11_screen *xscr)
+{
+ if (xscr->dri_fd >= 0)
+ close(xscr->dri_fd);
+ if (xscr->dri_driver)
+ Xfree(xscr->dri_driver);
+ if (xscr->dri_device)
+ Xfree(xscr->dri_device);
+
+ if (xscr->glx_dpy)
+ __glXRelease(xscr->glx_dpy);
+ if (xscr->visuals)
+ XFree(xscr->visuals);
+ free(xscr);
+}
+
+static boolean
+x11_screen_init_dri2(struct x11_screen *xscr)
+{
+ if (xscr->dri_major < 0) {
+ int eventBase, errorBase;
+
+ if (!DRI2QueryExtension(xscr->dpy, &eventBase, &errorBase) ||
+ !DRI2QueryVersion(xscr->dpy, &xscr->dri_major, &xscr->dri_minor))
+ xscr->dri_major = -1;
+ }
+ return (xscr->dri_major >= 0);
+}
+
+static boolean
+x11_screen_init_glx(struct x11_screen *xscr)
+{
+ if (!xscr->glx_dpy)
+ xscr->glx_dpy = __glXInitialize(xscr->dpy);
+ return (xscr->glx_dpy != NULL);
+}
+
+/**
+ * Return true if the screen supports the extension.
+ */
+boolean
+x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext)
+{
+ boolean supported = FALSE;
+
+ switch (ext) {
+ case X11_SCREEN_EXTENSION_XSHM:
+ supported = XShmQueryExtension(xscr->dpy);
+ break;
+ case X11_SCREEN_EXTENSION_GLX:
+ supported = x11_screen_init_glx(xscr);
+ break;
+ case X11_SCREEN_EXTENSION_DRI2:
+ supported = x11_screen_init_dri2(xscr);
+ break;
+ default:
+ break;
+ }
+
+ return supported;
+}
+
+/**
+ * Return the X visuals.
+ */
+const XVisualInfo *
+x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals)
+{
+ if (!xscr->visuals) {
+ XVisualInfo vinfo_template;
+ vinfo_template.screen = xscr->number;
+ xscr->visuals = XGetVisualInfo(xscr->dpy, VisualScreenMask,
+ &vinfo_template, &xscr->num_visuals);
+ }
+
+ if (num_visuals)
+ *num_visuals = xscr->num_visuals;
+ return xscr->visuals;
+}
+
+void
+x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual,
+ __GLcontextModes *mode)
+{
+ int r, g, b, a;
+ int visual_type;
+
+ r = util_bitcount(visual->red_mask);
+ g = util_bitcount(visual->green_mask);
+ b = util_bitcount(visual->blue_mask);
+ a = visual->depth - (r + g + b);
+#if defined(__cplusplus) || defined(c_plusplus)
+ visual_type = visual->c_class;
+#else
+ visual_type = visual->class;
+#endif
+
+ /* convert to GLX visual type */
+ switch (visual_type) {
+ case TrueColor:
+ visual_type = GLX_TRUE_COLOR;
+ break;
+ case DirectColor:
+ visual_type = GLX_DIRECT_COLOR;
+ break;
+ case PseudoColor:
+ visual_type = GLX_PSEUDO_COLOR;
+ break;
+ case StaticColor:
+ visual_type = GLX_STATIC_COLOR;
+ break;
+ case GrayScale:
+ visual_type = GLX_GRAY_SCALE;
+ break;
+ case StaticGray:
+ visual_type = GLX_STATIC_GRAY;
+ break;
+ default:
+ visual_type = GLX_NONE;
+ break;
+ }
+
+ mode->rgbBits = r + g + b + a;
+ mode->redBits = r;
+ mode->greenBits = g;
+ mode->blueBits = b;
+ mode->alphaBits = a;
+ mode->visualID = visual->visualid;
+ mode->visualType = visual_type;
+
+ /* sane defaults */
+ mode->renderType = GLX_RGBA_BIT;
+ mode->rgbMode = TRUE;
+ mode->visualRating = GLX_SLOW_CONFIG;
+ mode->xRenderable = TRUE;
+}
+
+/**
+ * Return the GLX fbconfigs.
+ */
+const __GLcontextModes *
+x11_screen_get_glx_configs(struct x11_screen *xscr)
+{
+ return (x11_screen_init_glx(xscr))
+ ? xscr->glx_dpy->screenConfigs[xscr->number].configs
+ : NULL;
+}
+
+/**
+ * Return the GLX visuals.
+ */
+const __GLcontextModes *
+x11_screen_get_glx_visuals(struct x11_screen *xscr)
+{
+ return (x11_screen_init_glx(xscr))
+ ? xscr->glx_dpy->screenConfigs[xscr->number].visuals
+ : NULL;
+}
+
+static boolean
+x11_screen_is_driver_equal(struct x11_screen *xscr, const char *driver)
+{
+ return (strcmp(xscr->dri_driver, driver) == 0);
+}
+
+/**
+ * Enable DRI2 and returns the file descriptor of the DRM device. The file
+ * descriptor will be closed automatically when the screen is destoryed.
+ */
+int
+x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver)
+{
+ if (xscr->dri_fd < 0) {
+ int fd;
+ 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_is_driver_equal(xscr, driver)) {
+ _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
+ xscr->dri_driver, driver);
+ return -1;
+ }
+
+ fd = open(xscr->dri_device, O_RDWR);
+ if (fd < 0) {
+ _eglLog(_EGL_WARNING, "failed to open %s", xscr->dri_device);
+ return -1;
+ }
+
+ memset(&magic, 0, sizeof(magic));
+ if (drmGetMagic(fd, &magic)) {
+ _eglLog(_EGL_WARNING, "failed to get magic");
+ close(fd);
+ return -1;
+ }
+
+ if (!DRI2Authenticate(xscr->dpy,
+ RootWindow(xscr->dpy, xscr->number), magic)) {
+ _eglLog(_EGL_WARNING, "failed to authenticate magic");
+ close(fd);
+ return -1;
+ }
+
+ xscr->dri_fd = fd;
+ }
+
+ return xscr->dri_fd;
+}
+
+/**
+ * Create/Destroy the DRI drawable.
+ */
+void
+x11_drawable_enable_dri2(struct x11_screen *xscr,
+ Drawable drawable, boolean on)
+{
+ if (on)
+ DRI2CreateDrawable(xscr->dpy, drawable);
+ else
+ DRI2DestroyDrawable(xscr->dpy, drawable);
+}
+
+/**
+ * Copy between buffers of the DRI2 drawable.
+ */
+void
+x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable,
+ int x, int y, int width, int height,
+ int src_buf, int dst_buf)
+{
+ XRectangle rect;
+ XserverRegion region;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+
+ region = XFixesCreateRegion(xscr->dpy, &rect, 1);
+ DRI2CopyRegion(xscr->dpy, drawable, region, dst_buf, src_buf);
+ XFixesDestroyRegion(xscr->dpy, region);
+}
+
+/**
+ * Get the buffers of the DRI2 drawable. The returned array should be freed.
+ */
+struct x11_drawable_buffer *
+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)
+{
+ DRI2Buffer *dri2bufs;
+
+ if (with_format)
+ dri2bufs = DRI2GetBuffersWithFormat(xscr->dpy, drawable, width, height,
+ attachments, num_ins, num_outs);
+ else
+ dri2bufs = DRI2GetBuffers(xscr->dpy, drawable, width, height,
+ attachments, num_ins, num_outs);
+
+ return (struct x11_drawable_buffer *) dri2bufs;
+}
+
+/**
+ * Create a mode list of the given size.
+ */
+__GLcontextModes *
+x11_context_modes_create(unsigned count)
+{
+ const size_t size = sizeof(__GLcontextModes);
+ __GLcontextModes *base = NULL;
+ __GLcontextModes **next;
+ unsigned i;
+
+ next = &base;
+ for (i = 0; i < count; i++) {
+ *next = (__GLcontextModes *) calloc(1, size);
+ if (*next == NULL) {
+ x11_context_modes_destroy(base);
+ base = NULL;
+ break;
+ }
+ next = &((*next)->next);
+ }
+
+ return base;
+}
+
+/**
+ * Destroy a mode list.
+ */
+void
+x11_context_modes_destroy(__GLcontextModes *modes)
+{
+ while (modes != NULL) {
+ __GLcontextModes *next = modes->next;
+ free(modes);
+ modes = next;
+ }
+}
+
+/**
+ * Return the number of the modes in the mode list.
+ */
+unsigned
+x11_context_modes_count(const __GLcontextModes *modes)
+{
+ const __GLcontextModes *mode;
+ int count = 0;
+ for (mode = modes; mode; mode = mode->next)
+ count++;
+ return count;
+}
diff --git a/src/gallium/state_trackers/egl_g3d/x11/x11_screen.h b/src/gallium/state_trackers/egl_g3d/x11/x11_screen.h
new file mode 100644
index 00000000000..86e8e0501a3
--- /dev/null
+++ b/src/gallium/state_trackers/egl_g3d/x11/x11_screen.h
@@ -0,0 +1,99 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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 _X11_SCREEN_H_
+#define _X11_SCREEN_H_
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/dri2tokens.h>
+#include "pipe/p_compiler.h"
+#include "common/native.h"
+
+enum x11_screen_extension {
+ X11_SCREEN_EXTENSION_XSHM,
+ X11_SCREEN_EXTENSION_GLX,
+ X11_SCREEN_EXTENSION_DRI2,
+};
+
+/* the same as DRI2Buffer */
+struct x11_drawable_buffer {
+ unsigned int attachment;
+ unsigned int name;
+ unsigned int pitch;
+ unsigned int cpp;
+ unsigned int flags;
+};
+
+struct x11_screen;
+
+struct x11_screen *
+x11_screen_create(Display *dpy, int screen);
+
+void
+x11_screen_destroy(struct x11_screen *xscr);
+
+boolean
+x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext);
+
+const XVisualInfo *
+x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals);
+
+void
+x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual,
+ __GLcontextModes *mode);
+
+const __GLcontextModes *
+x11_screen_get_glx_configs(struct x11_screen *xscr);
+
+const __GLcontextModes *
+x11_screen_get_glx_visuals(struct x11_screen *xscr);
+
+int
+x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver);
+
+__GLcontextModes *
+x11_context_modes_create(unsigned count);
+
+void
+x11_context_modes_destroy(__GLcontextModes *modes);
+
+unsigned
+x11_context_modes_count(const __GLcontextModes *modes);
+
+void
+x11_drawable_enable_dri2(struct x11_screen *xscr,
+ Drawable drawable, boolean on);
+
+void
+x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable,
+ int x, int y, int width, int height,
+ int src_buf, int dst_buf);
+
+struct x11_drawable_buffer *
+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);
+
+#endif /* _X11_SCREEN_H_ */
diff --git a/src/gallium/state_trackers/glx/xlib/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c
index 228ac9a20e9..3caf56e924b 100644
--- a/src/gallium/state_trackers/glx/xlib/glx_api.c
+++ b/src/gallium/state_trackers/glx/xlib/glx_api.c
@@ -1007,7 +1007,7 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
}
-XVisualInfo *
+PUBLIC XVisualInfo *
glXChooseVisual( Display *dpy, int screen, int *list )
{
XMesaVisual xmvis;
@@ -1029,7 +1029,7 @@ glXChooseVisual( Display *dpy, int screen, int *list )
}
-GLXContext
+PUBLIC GLXContext
glXCreateContext( Display *dpy, XVisualInfo *visinfo,
GLXContext share_list, Bool direct )
{
@@ -1084,7 +1084,7 @@ static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
/* GLX 1.3 and later */
-Bool
+PUBLIC Bool
glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
GLXDrawable read, GLXContext ctx )
{
@@ -1180,21 +1180,21 @@ glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
}
-Bool
+PUBLIC Bool
glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
{
return glXMakeContextCurrent( dpy, drawable, drawable, ctx );
}
-GLXContext
+PUBLIC GLXContext
glXGetCurrentContext(void)
{
return GetCurrentContext();
}
-Display *
+PUBLIC Display *
glXGetCurrentDisplay(void)
{
GLXContext glxCtx = glXGetCurrentContext();
@@ -1203,14 +1203,14 @@ glXGetCurrentDisplay(void)
}
-Display *
+PUBLIC Display *
glXGetCurrentDisplayEXT(void)
{
return glXGetCurrentDisplay();
}
-GLXDrawable
+PUBLIC GLXDrawable
glXGetCurrentDrawable(void)
{
GLXContext gc = glXGetCurrentContext();
@@ -1218,7 +1218,7 @@ glXGetCurrentDrawable(void)
}
-GLXDrawable
+PUBLIC GLXDrawable
glXGetCurrentReadDrawable(void)
{
GLXContext gc = glXGetCurrentContext();
@@ -1226,14 +1226,14 @@ glXGetCurrentReadDrawable(void)
}
-GLXDrawable
+PUBLIC GLXDrawable
glXGetCurrentReadDrawableSGI(void)
{
return glXGetCurrentReadDrawable();
}
-GLXPixmap
+PUBLIC GLXPixmap
glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
{
XMesaVisual v;
@@ -1258,7 +1258,7 @@ glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
/*** GLX_MESA_pixmap_colormap ***/
-GLXPixmap
+PUBLIC GLXPixmap
glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
Pixmap pixmap, Colormap cmap )
{
@@ -1282,7 +1282,7 @@ glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
}
-void
+PUBLIC void
glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
{
XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
@@ -1295,7 +1295,7 @@ glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
}
-void
+PUBLIC void
glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
unsigned long mask )
{
@@ -1309,7 +1309,7 @@ glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
}
-Bool
+PUBLIC Bool
glXQueryExtension( Display *dpy, int *errorBase, int *eventBase )
{
int op, ev, err;
@@ -1324,7 +1324,7 @@ glXQueryExtension( Display *dpy, int *errorBase, int *eventBase )
}
-void
+PUBLIC void
glXDestroyContext( Display *dpy, GLXContext ctx )
{
GLXContext glxCtx = ctx;
@@ -1340,7 +1340,7 @@ glXDestroyContext( Display *dpy, GLXContext ctx )
}
-Bool
+PUBLIC Bool
glXIsDirect( Display *dpy, GLXContext ctx )
{
GLXContext glxCtx = ctx;
@@ -1350,7 +1350,7 @@ glXIsDirect( Display *dpy, GLXContext ctx )
-void
+PUBLIC void
glXSwapBuffers( Display *dpy, GLXDrawable drawable )
{
XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
@@ -1377,7 +1377,7 @@ glXSwapBuffers( Display *dpy, GLXDrawable drawable )
/*** GLX_MESA_copy_sub_buffer ***/
-void
+PUBLIC void
glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
int x, int y, int width, int height )
{
@@ -1391,7 +1391,7 @@ glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
}
-Bool
+PUBLIC Bool
glXQueryVersion( Display *dpy, int *maj, int *min )
{
(void) dpy;
@@ -1608,7 +1608,7 @@ get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
}
-int
+PUBLIC int
glXGetConfig( Display *dpy, XVisualInfo *visinfo,
int attrib, int *value )
{
@@ -1638,7 +1638,7 @@ glXGetConfig( Display *dpy, XVisualInfo *visinfo,
}
-void
+PUBLIC void
glXWaitGL( void )
{
XMesaContext xmesa = XMesaGetCurrentContext();
@@ -1647,7 +1647,7 @@ glXWaitGL( void )
-void
+PUBLIC void
glXWaitX( void )
{
XMesaContext xmesa = XMesaGetCurrentContext();
@@ -1664,7 +1664,7 @@ get_extensions( void )
/* GLX 1.1 and later */
-const char *
+PUBLIC const char *
glXQueryExtensionsString( Display *dpy, int screen )
{
(void) dpy;
@@ -1675,7 +1675,7 @@ glXQueryExtensionsString( Display *dpy, int screen )
/* GLX 1.1 and later */
-const char *
+PUBLIC const char *
glXQueryServerString( Display *dpy, int screen, int name )
{
static char version[1000];
@@ -1700,7 +1700,7 @@ glXQueryServerString( Display *dpy, int screen, int name )
/* GLX 1.1 and later */
-const char *
+PUBLIC const char *
glXGetClientString( Display *dpy, int name )
{
static char version[1000];
@@ -1728,7 +1728,7 @@ glXGetClientString( Display *dpy, int name )
*/
-int
+PUBLIC int
glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
int attribute, int *value )
{
@@ -1743,7 +1743,7 @@ glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
}
-GLXFBConfig *
+PUBLIC GLXFBConfig *
glXGetFBConfigs( Display *dpy, int screen, int *nelements )
{
XVisualInfo *visuals, visTemplate;
@@ -1769,7 +1769,7 @@ glXGetFBConfigs( Display *dpy, int screen, int *nelements )
}
-GLXFBConfig *
+PUBLIC GLXFBConfig *
glXChooseFBConfig( Display *dpy, int screen,
const int *attribList, int *nitems )
{
@@ -1798,7 +1798,7 @@ glXChooseFBConfig( Display *dpy, int screen,
}
-XVisualInfo *
+PUBLIC XVisualInfo *
glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
{
if (dpy && config) {
@@ -1820,7 +1820,7 @@ glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
}
-GLXWindow
+PUBLIC GLXWindow
glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
const int *attribList )
{
@@ -1840,7 +1840,7 @@ glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
}
-void
+PUBLIC void
glXDestroyWindow( Display *dpy, GLXWindow window )
{
XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window);
@@ -1851,7 +1851,7 @@ glXDestroyWindow( Display *dpy, GLXWindow window )
/* XXX untested */
-GLXPixmap
+PUBLIC GLXPixmap
glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
const int *attribList )
{
@@ -1961,7 +1961,7 @@ glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
}
-void
+PUBLIC void
glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
{
XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap);
@@ -1971,7 +1971,7 @@ glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
}
-GLXPbuffer
+PUBLIC GLXPbuffer
glXCreatePbuffer( Display *dpy, GLXFBConfig config,
const int *attribList )
{
@@ -2034,7 +2034,7 @@ glXCreatePbuffer( Display *dpy, GLXFBConfig config,
}
-void
+PUBLIC void
glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
{
XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);
@@ -2044,7 +2044,7 @@ glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
}
-void
+PUBLIC void
glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
unsigned int *value )
{
@@ -2090,7 +2090,7 @@ glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
}
-GLXContext
+PUBLIC GLXContext
glXCreateNewContext( Display *dpy, GLXFBConfig config,
int renderType, GLXContext shareList, Bool direct )
{
@@ -2124,7 +2124,7 @@ glXCreateNewContext( Display *dpy, GLXFBConfig config,
}
-int
+PUBLIC int
glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
{
GLXContext glxCtx = ctx;
@@ -2153,7 +2153,7 @@ glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
}
-void
+PUBLIC void
glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
{
XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
@@ -2162,7 +2162,7 @@ glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
}
-void
+PUBLIC void
glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
unsigned long *mask )
{
@@ -2177,7 +2177,7 @@ glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
/*** GLX_SGI_swap_control ***/
-int
+PUBLIC int
glXSwapIntervalSGI(int interval)
{
(void) interval;
@@ -2190,7 +2190,7 @@ glXSwapIntervalSGI(int interval)
static unsigned int FrameCounter = 0;
-int
+PUBLIC int
glXGetVideoSyncSGI(unsigned int *count)
{
/* this is a bogus implementation */
@@ -2198,7 +2198,7 @@ glXGetVideoSyncSGI(unsigned int *count)
return 0;
}
-int
+PUBLIC int
glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
{
if (divisor <= 0 || remainder < 0)
@@ -2215,7 +2215,7 @@ glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
/*** GLX_SGI_make_current_read ***/
-Bool
+PUBLIC Bool
glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
{
return glXMakeContextCurrent( dpy, draw, read, ctx );
@@ -2233,7 +2233,7 @@ glXGetCurrentReadDrawableSGI(void)
/*** GLX_SGIX_video_source ***/
#if defined(_VL_H)
-GLXVideoSourceSGIX
+PUBLIC GLXVideoSourceSGIX
glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode)
{
(void) dpy;
@@ -2245,7 +2245,7 @@ glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath pa
return 0;
}
-void
+PUBLIC void
glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
{
(void) dpy;
@@ -2257,21 +2257,21 @@ glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
/*** GLX_EXT_import_context ***/
-void
+PUBLIC void
glXFreeContextEXT(Display *dpy, GLXContext context)
{
(void) dpy;
(void) context;
}
-GLXContextID
+PUBLIC GLXContextID
glXGetContextIDEXT(const GLXContext context)
{
(void) context;
return 0;
}
-GLXContext
+PUBLIC GLXContext
glXImportContextEXT(Display *dpy, GLXContextID contextID)
{
(void) dpy;
@@ -2279,7 +2279,7 @@ glXImportContextEXT(Display *dpy, GLXContextID contextID)
return 0;
}
-int
+PUBLIC int
glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value)
{
(void) dpy;
@@ -2293,20 +2293,20 @@ glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *val
/*** GLX_SGIX_fbconfig ***/
-int
+PUBLIC int
glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value)
{
return glXGetFBConfigAttrib(dpy, config, attribute, value);
}
-GLXFBConfigSGIX *
+PUBLIC GLXFBConfigSGIX *
glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements)
{
return (GLXFBConfig *) glXChooseFBConfig(dpy, screen, attrib_list, nelements);
}
-GLXPixmap
+PUBLIC GLXPixmap
glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap)
{
XMesaVisual xmvis = (XMesaVisual) config;
@@ -2315,7 +2315,7 @@ glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pi
}
-GLXContext
+PUBLIC GLXContext
glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct)
{
XMesaVisual xmvis = (XMesaVisual) config;
@@ -2344,14 +2344,14 @@ glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_
}
-XVisualInfo *
+PUBLIC XVisualInfo *
glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
{
return glXGetVisualFromFBConfig(dpy, config);
}
-GLXFBConfigSGIX
+PUBLIC GLXFBConfigSGIX
glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
{
XMesaVisual xmvis = find_glx_visual(dpy, vis);
@@ -2367,7 +2367,7 @@ glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
/*** GLX_SGIX_pbuffer ***/
-GLXPbufferSGIX
+PUBLIC GLXPbufferSGIX
glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
unsigned int width, unsigned int height,
int *attribList)
@@ -2406,7 +2406,7 @@ glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
}
-void
+PUBLIC void
glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
{
XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
@@ -2416,7 +2416,7 @@ glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
}
-int
+PUBLIC int
glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value)
{
const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
@@ -2449,7 +2449,7 @@ glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigne
}
-void
+PUBLIC void
glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
{
XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
@@ -2460,7 +2460,7 @@ glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
}
-void
+PUBLIC void
glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask)
{
XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
@@ -2476,7 +2476,7 @@ glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask)
/*** GLX_SGI_cushion ***/
-void
+PUBLIC void
glXCushionSGI(Display *dpy, Window win, float cushion)
{
(void) dpy;
@@ -2488,7 +2488,7 @@ glXCushionSGI(Display *dpy, Window win, float cushion)
/*** GLX_SGIX_video_resize ***/
-int
+PUBLIC int
glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window)
{
(void) dpy;
@@ -2498,7 +2498,7 @@ glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window
return 0;
}
-int
+PUBLIC int
glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h)
{
(void) dpy;
@@ -2511,7 +2511,7 @@ glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, i
return 0;
}
-int
+PUBLIC int
glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h)
{
(void) dpy;
@@ -2524,7 +2524,7 @@ glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, i
return 0;
}
-int
+PUBLIC int
glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh)
{
(void) dpy;
@@ -2537,7 +2537,7 @@ glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *d
return 0;
}
-int
+PUBLIC int
glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
{
(void) dpy;
@@ -2552,7 +2552,7 @@ glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
/*** GLX_SGIX_dmbuffer **/
#if defined(_DM_BUFFER_H_)
-Bool
+PUBLIC Bool
glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer)
{
(void) dpy;
@@ -2566,7 +2566,7 @@ glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params
/*** GLX_SGIX_swap_group ***/
-void
+PUBLIC void
glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
{
(void) dpy;
@@ -2578,7 +2578,7 @@ glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
/*** GLX_SGIX_swap_barrier ***/
-void
+PUBLIC void
glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
{
(void) dpy;
@@ -2586,7 +2586,7 @@ glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
(void) barrier;
}
-Bool
+PUBLIC Bool
glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
{
(void) dpy;
@@ -2599,7 +2599,7 @@ glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
/*** GLX_SUN_get_transparent_index ***/
-Status
+PUBLIC Status
glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent)
{
(void) dpy;
@@ -2617,7 +2617,7 @@ glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *p
* Release the depth, stencil, accum buffers attached to a GLXDrawable
* (a window or pixmap) prior to destroying the GLXDrawable.
*/
-Bool
+PUBLIC Bool
glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
{
XMesaBuffer b = XMesaFindBuffer(dpy, d);
@@ -2630,7 +2630,7 @@ glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
/*** GLX_EXT_texture_from_pixmap ***/
-void
+PUBLIC void
glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
const int *attrib_list)
{
@@ -2639,7 +2639,7 @@ glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
XMesaBindTexImage(dpy, b, buffer, attrib_list);
}
-void
+PUBLIC void
glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
{
XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
diff --git a/src/gallium/state_trackers/glx/xlib/glx_getproc.c b/src/gallium/state_trackers/glx/xlib/glx_getproc.c
index ca7d88c9227..84d47b12edc 100644
--- a/src/gallium/state_trackers/glx/xlib/glx_getproc.c
+++ b/src/gallium/state_trackers/glx/xlib/glx_getproc.c
@@ -34,6 +34,7 @@
#include <string.h>
#include "GL/glx.h"
#include "glapi/glapi.h"
+#include "pipe/p_compiler.h"
struct name_address_pair {
@@ -208,6 +209,7 @@ glXGetProcAddressARB(const GLubyte *procName)
/* GLX 1.4 */
+PUBLIC
void (*glXGetProcAddress(const GLubyte *procName))()
{
return glXGetProcAddressARB(procName);
diff --git a/src/gallium/state_trackers/glx/xlib/glx_usefont.c b/src/gallium/state_trackers/glx/xlib/glx_usefont.c
index acc64df62b6..16e5ce642f3 100644
--- a/src/gallium/state_trackers/glx/xlib/glx_usefont.c
+++ b/src/gallium/state_trackers/glx/xlib/glx_usefont.c
@@ -33,6 +33,7 @@
#include "main/context.h"
#include "main/imports.h"
#include <GL/glx.h>
+#include "pipe/p_compiler.h"
/* Some debugging info. */
@@ -210,7 +211,7 @@ isvalid(XFontStruct * fs, unsigned int which)
}
-void
+PUBLIC void
glXUseXFont(Font font, int first, int count, int listbase)
{
Display *dpy;
diff --git a/src/gallium/state_trackers/python/SConscript b/src/gallium/state_trackers/python/SConscript
index d4fdd43688f..8498a90812e 100644
--- a/src/gallium/state_trackers/python/SConscript
+++ b/src/gallium/state_trackers/python/SConscript
@@ -28,14 +28,27 @@ if 'python' in env['statetrackers']:
'X11',
])
+ sources = [
+ 'gallium.i',
+ 'st_device.c',
+ 'st_sample.c',
+ ]
+
+ drivers = [
+ trace
+ ]
+
+ if 'llvmpipe' in env['drivers']:
+ env.Tool('llvm')
+ sources += ['st_llvmpipe_winsys.c']
+ drivers += [llvmpipe]
+ else:
+ sources += ['st_softpipe_winsys.c']
+ drivers += [softpipe]
+
pyst = env.ConvenienceLibrary(
target = 'pyst',
- source = [
- 'gallium.i',
- 'st_device.c',
- 'st_sample.c',
- 'st_softpipe_winsys.c',
- ],
+ source = sources,
)
env['no_import_lib'] = 1
@@ -45,5 +58,5 @@ if 'python' in env['statetrackers']:
source = [
'st_hardpipe_winsys.c',
],
- LIBS = [pyst, softpipe, trace] + gallium + env['LIBS'],
+ LIBS = [pyst] + drivers + gallium + env['LIBS'],
)
diff --git a/src/gallium/state_trackers/python/gallium.i b/src/gallium/state_trackers/python/gallium.i
index 96b13c2258e..68797228459 100644
--- a/src/gallium/state_trackers/python/gallium.i
+++ b/src/gallium/state_trackers/python/gallium.i
@@ -76,7 +76,6 @@
%rename(BlendColor) pipe_blend_color;
%rename(Blend) pipe_blend_state;
%rename(Clip) pipe_clip_state;
-%rename(ConstantBuffer) pipe_constant_buffer;
%rename(Depth) pipe_depth_state;
%rename(Stencil) pipe_stencil_state;
%rename(Alpha) pipe_alpha_state;
diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i
index 84ce1a41e6d..ce893dad453 100644
--- a/src/gallium/state_trackers/python/p_context.i
+++ b/src/gallium/state_trackers/python/p_context.i
@@ -142,10 +142,7 @@ struct st_context {
void set_constant_buffer(unsigned shader, unsigned index,
struct pipe_buffer *buffer )
{
- struct pipe_constant_buffer state;
- memset(&state, 0, sizeof(state));
- state.buffer = buffer;
- $self->pipe->set_constant_buffer($self->pipe, shader, index, &state);
+ $self->pipe->set_constant_buffer($self->pipe, shader, index, buffer);
}
void set_framebuffer(const struct pipe_framebuffer_state *state )
diff --git a/src/gallium/state_trackers/python/p_device.i b/src/gallium/state_trackers/python/p_device.i
index 2dc995adb07..0eba488a078 100644
--- a/src/gallium/state_trackers/python/p_device.i
+++ b/src/gallium/state_trackers/python/p_device.i
@@ -87,6 +87,10 @@ struct st_device {
enum pipe_texture_target target,
unsigned tex_usage,
unsigned geom_flags ) {
+ /* We can't really display surfaces with the python statetracker so mask
+ * out that usage */
+ tex_usage &= ~PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+
return $self->screen->is_format_supported( $self->screen,
format,
target,
@@ -110,6 +114,11 @@ struct st_device {
unsigned tex_usage = 0
) {
struct pipe_texture templat;
+
+ /* We can't really display surfaces with the python statetracker so mask
+ * out that usage */
+ tex_usage &= ~PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+
memset(&templat, 0, sizeof(templat));
templat.format = format;
templat.width0 = width;
@@ -118,6 +127,7 @@ struct st_device {
templat.last_level = last_level;
templat.target = target;
templat.tex_usage = tex_usage;
+
return $self->screen->texture_create($self->screen, &templat);
}
diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py
index a68709f5cf3..b61d47d6456 100755
--- a/src/gallium/state_trackers/python/retrace/interpreter.py
+++ b/src/gallium/state_trackers/python/retrace/interpreter.py
@@ -94,7 +94,7 @@ struct_factories = {
"pipe_blend_color": gallium.BlendColor,
"pipe_blend_state": gallium.Blend,
#"pipe_clip_state": gallium.Clip,
- #"pipe_constant_buffer": gallium.ConstantBuffer,
+ #"pipe_buffer": gallium.Buffer,
"pipe_depth_state": gallium.Depth,
"pipe_stencil_state": gallium.Stencil,
"pipe_alpha_state": gallium.Alpha,
@@ -462,10 +462,10 @@ class Context(Object):
sys.stdout.flush()
def set_constant_buffer(self, shader, index, buffer):
- if buffer is not None and buffer.buffer is not None:
- self.real.set_constant_buffer(shader, index, buffer.buffer)
+ if buffer is not None:
+ self.real.set_constant_buffer(shader, index, buffer)
- self.dump_constant_buffer(buffer.buffer)
+ self.dump_constant_buffer(buffer)
def set_framebuffer_state(self, state):
_state = gallium.Framebuffer()
diff --git a/src/gallium/state_trackers/python/samples/gs.py b/src/gallium/state_trackers/python/samples/gs.py
index 1ceead5f17c..a07cf557f2f 100644
--- a/src/gallium/state_trackers/python/samples/gs.py
+++ b/src/gallium/state_trackers/python/samples/gs.py
@@ -136,10 +136,10 @@ def test(dev):
cbuf = dev.texture_create(
PIPE_FORMAT_X8R8G8B8_UNORM,
width, height,
- tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET,
+ tex_usage=PIPE_TEXTURE_USAGE_RENDER_TARGET,
).get_surface()
zbuf = dev.texture_create(
- PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
width, height,
tex_usage=PIPE_TEXTURE_USAGE_DEPTH_STENCIL,
).get_surface()
diff --git a/src/gallium/state_trackers/python/samples/tri.py b/src/gallium/state_trackers/python/samples/tri.py
index af80426dc6c..e5e168bdc8d 100644
--- a/src/gallium/state_trackers/python/samples/tri.py
+++ b/src/gallium/state_trackers/python/samples/tri.py
@@ -136,10 +136,10 @@ def test(dev):
cbuf = dev.texture_create(
PIPE_FORMAT_X8R8G8B8_UNORM,
width, height,
- tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET,
+ tex_usage=PIPE_TEXTURE_USAGE_RENDER_TARGET,
).get_surface()
zbuf = dev.texture_create(
- PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
width, height,
tex_usage=PIPE_TEXTURE_USAGE_DEPTH_STENCIL,
).get_surface()
diff --git a/src/gallium/state_trackers/python/st_llvmpipe_winsys.c b/src/gallium/state_trackers/python/st_llvmpipe_winsys.c
new file mode 100644
index 00000000000..0096b18c994
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_llvmpipe_winsys.c
@@ -0,0 +1,148 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE 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
+ * Llvmpipe support.
+ *
+ * @author Jose Fonseca
+ */
+
+
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "llvmpipe/lp_winsys.h"
+#include "st_winsys.h"
+
+
+static boolean
+llvmpipe_ws_is_displaytarget_format_supported( struct llvmpipe_winsys *ws,
+ enum pipe_format format )
+{
+ return FALSE;
+}
+
+
+static void *
+llvmpipe_ws_displaytarget_map(struct llvmpipe_winsys *ws,
+ struct llvmpipe_displaytarget *dt,
+ unsigned flags )
+{
+ assert(0);
+ return NULL;
+}
+
+
+static void
+llvmpipe_ws_displaytarget_unmap(struct llvmpipe_winsys *ws,
+ struct llvmpipe_displaytarget *dt )
+{
+ assert(0);
+}
+
+
+static void
+llvmpipe_ws_displaytarget_destroy(struct llvmpipe_winsys *winsys,
+ struct llvmpipe_displaytarget *dt)
+{
+ assert(0);
+}
+
+
+static struct llvmpipe_displaytarget *
+llvmpipe_ws_displaytarget_create(struct llvmpipe_winsys *winsys,
+ enum pipe_format format,
+ unsigned width, unsigned height,
+ unsigned alignment,
+ unsigned *stride)
+{
+ return NULL;
+}
+
+
+static void
+llvmpipe_ws_displaytarget_display(struct llvmpipe_winsys *winsys,
+ struct llvmpipe_displaytarget *dt,
+ void *context_private)
+{
+ assert(0);
+}
+
+
+static void
+llvmpipe_ws_destroy(struct llvmpipe_winsys *winsys)
+{
+ FREE(winsys);
+}
+
+
+static struct pipe_screen *
+st_llvmpipe_screen_create(void)
+{
+ static struct llvmpipe_winsys *winsys;
+ struct pipe_screen *screen;
+
+ winsys = CALLOC_STRUCT(llvmpipe_winsys);
+ if (!winsys)
+ goto no_winsys;
+
+ winsys->destroy = llvmpipe_ws_destroy;
+ winsys->is_displaytarget_format_supported = llvmpipe_ws_is_displaytarget_format_supported;
+ winsys->displaytarget_create = llvmpipe_ws_displaytarget_create;
+ winsys->displaytarget_map = llvmpipe_ws_displaytarget_map;
+ winsys->displaytarget_unmap = llvmpipe_ws_displaytarget_unmap;
+ winsys->displaytarget_display = llvmpipe_ws_displaytarget_display;
+ winsys->displaytarget_destroy = llvmpipe_ws_displaytarget_destroy;
+
+ screen = llvmpipe_create_screen(winsys);
+ if (!screen)
+ goto no_screen;
+
+ return screen;
+
+no_screen:
+ FREE(winsys);
+no_winsys:
+ return NULL;
+}
+
+
+static struct pipe_context *
+st_llvmpipe_context_create(struct pipe_screen *screen)
+{
+ return llvmpipe_create(screen);
+}
+
+
+const struct st_winsys st_softpipe_winsys = {
+ &st_llvmpipe_screen_create,
+ &st_llvmpipe_context_create,
+};
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/.gitignore b/src/gallium/state_trackers/python/tests/regress/fragment-shader/.gitignore
new file mode 100644
index 00000000000..e33609d251c
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/.gitignore
@@ -0,0 +1 @@
+*.png
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 eed6cdd1e64..8d3bf9d4d7e 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
@@ -114,7 +114,7 @@ def test(dev, name):
cbuf = dev.texture_create(
PIPE_FORMAT_X8R8G8B8_UNORM,
width, height,
- tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET,
+ tex_usage=PIPE_TEXTURE_USAGE_RENDER_TARGET,
).get_surface()
fb = Framebuffer()
fb.width = width
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/.gitignore b/src/gallium/state_trackers/python/tests/regress/vertex-shader/.gitignore
new file mode 100644
index 00000000000..e33609d251c
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/.gitignore
@@ -0,0 +1 @@
+*.png
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 41bebd0604a..01bf5a3210d 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
@@ -114,7 +114,7 @@ def test(dev, name):
cbuf = dev.texture_create(
PIPE_FORMAT_X8R8G8B8_UNORM,
width, height,
- tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET,
+ tex_usage=PIPE_TEXTURE_USAGE_RENDER_TARGET,
).get_surface()
fb = Framebuffer()
fb.width = width
diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c
index 2f984fb7b9a..8f69ee01099 100644
--- a/src/gallium/state_trackers/vega/api_filters.c
+++ b/src/gallium/state_trackers/vega/api_filters.c
@@ -147,22 +147,22 @@ static void setup_constant_buffer(struct vg_context *ctx, const void *buffer,
VGint param_bytes)
{
struct pipe_context *pipe = ctx->pipe;
- struct pipe_constant_buffer *cbuf = &ctx->filter.buffer;
+ struct pipe_buffer **cbuf = &ctx->filter.buffer;
/* We always need to get a new buffer, to keep the drivers simple and
* avoid gratuitous rendering synchronization. */
- pipe_buffer_reference(&cbuf->buffer, NULL);
+ pipe_buffer_reference(cbuf, NULL);
- cbuf->buffer = pipe_buffer_create(pipe->screen, 16,
- PIPE_BUFFER_USAGE_CONSTANT,
- param_bytes);
+ *cbuf = pipe_buffer_create(pipe->screen, 16,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
- if (cbuf->buffer) {
- st_no_flush_pipe_buffer_write(ctx, cbuf->buffer,
+ if (*cbuf) {
+ st_no_flush_pipe_buffer_write(ctx, *cbuf,
0, param_bytes, buffer);
}
- ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+ ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf);
}
static void setup_samplers(struct vg_context *ctx, struct filter_info *info)
diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c
index 42300bb6d57..3e260e70736 100644
--- a/src/gallium/state_trackers/vega/mask.c
+++ b/src/gallium/state_trackers/vega/mask.c
@@ -217,7 +217,7 @@ static void setup_mask_framebuffer(struct pipe_surface *surf,
static void setup_mask_operation(VGMaskOperation operation)
{
struct vg_context *ctx = vg_current_context();
- struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf;
+ struct pipe_buffer **cbuf = &ctx->mask.cbuf;
const VGint param_bytes = 4 * sizeof(VGfloat);
const VGfloat ones[4] = {1.f, 1.f, 1.f, 1.f};
void *shader = 0;
@@ -225,17 +225,17 @@ static void setup_mask_operation(VGMaskOperation operation)
/* We always need to get a new buffer, to keep the drivers simple and
* avoid gratuitous rendering synchronization.
*/
- pipe_buffer_reference(&cbuf->buffer, NULL);
+ pipe_buffer_reference(cbuf, NULL);
- cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 1,
- PIPE_BUFFER_USAGE_CONSTANT,
- param_bytes);
- if (cbuf->buffer) {
- st_no_flush_pipe_buffer_write(ctx, cbuf->buffer,
+ *cbuf = pipe_buffer_create(ctx->pipe->screen, 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
+ if (*cbuf) {
+ st_no_flush_pipe_buffer_write(ctx, *cbuf,
0, param_bytes, ones);
}
- ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+ ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf);
switch (operation) {
case VG_UNION_MASK: {
if (!ctx->mask.union_fs) {
@@ -320,22 +320,22 @@ static void setup_mask_samplers(struct pipe_texture *umask)
static void setup_mask_fill(const VGfloat color[4])
{
struct vg_context *ctx = vg_current_context();
- struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf;
+ struct pipe_buffer **cbuf = &ctx->mask.cbuf;
const VGint param_bytes = 4 * sizeof(VGfloat);
/* We always need to get a new buffer, to keep the drivers simple and
* avoid gratuitous rendering synchronization.
*/
- pipe_buffer_reference(&cbuf->buffer, NULL);
+ pipe_buffer_reference(cbuf, NULL);
- cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 1,
- PIPE_BUFFER_USAGE_CONSTANT,
- param_bytes);
- if (cbuf->buffer) {
- st_no_flush_pipe_buffer_write(ctx, cbuf->buffer, 0, param_bytes, color);
+ *cbuf = pipe_buffer_create(ctx->pipe->screen, 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
+ if (*cbuf) {
+ st_no_flush_pipe_buffer_write(ctx, *cbuf, 0, param_bytes, color);
}
- ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+ ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf);
cso_set_fragment_shader_handle(ctx->cso_context,
shaders_cache_fill(ctx->sc,
VEGA_SOLID_FILL_SHADER));
diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c
index cc73771d358..d8f6299b2db 100644
--- a/src/gallium/state_trackers/vega/paint.c
+++ b/src/gallium/state_trackers/vega/paint.c
@@ -77,7 +77,8 @@ struct vg_paint {
struct pipe_sampler_state sampler;
} pattern;
- struct pipe_constant_buffer cbuf;
+ /* XXX next 3 all unneded? */
+ struct pipe_buffer *cbuf;
struct pipe_shader_state fs_state;
void *fs;
};
diff --git a/src/gallium/state_trackers/vega/polygon.c b/src/gallium/state_trackers/vega/polygon.c
index b6d282d803b..d385ee567fa 100644
--- a/src/gallium/state_trackers/vega/polygon.c
+++ b/src/gallium/state_trackers/vega/polygon.c
@@ -293,6 +293,7 @@ static void draw_polygon(struct vg_context *ctx,
/* tell pipe about the vertex attributes */
velement.src_offset = 0;
+ velement.instance_divisor = 0;
velement.vertex_buffer_index = 0;
velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
velement.nr_components = COMPONENTS;
diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c
index d9074a377b3..bd5ae79e551 100644
--- a/src/gallium/state_trackers/vega/shader.c
+++ b/src/gallium/state_trackers/vega/shader.c
@@ -51,7 +51,7 @@ struct shader {
VGImageMode image_mode;
float constants[MAX_CONSTANTS];
- struct pipe_constant_buffer cbuf;
+ struct pipe_buffer *cbuf;
struct pipe_shader_state fs_state;
void *fs;
};
@@ -96,25 +96,25 @@ static void setup_constant_buffer(struct shader *shader)
{
struct vg_context *ctx = shader->context;
struct pipe_context *pipe = shader->context->pipe;
- struct pipe_constant_buffer *cbuf = &shader->cbuf;
+ struct pipe_buffer **cbuf = &shader->cbuf;
VGint param_bytes = paint_constant_buffer_size(shader->paint);
float temp_buf[MAX_CONSTANTS];
assert(param_bytes <= sizeof(temp_buf));
paint_fill_constant_buffer(shader->paint, temp_buf);
- if (cbuf->buffer == NULL ||
+ if (*cbuf == NULL ||
memcmp(temp_buf, shader->constants, param_bytes) != 0)
{
- pipe_buffer_reference(&cbuf->buffer, NULL);
+ pipe_buffer_reference(cbuf, NULL);
memcpy(shader->constants, temp_buf, param_bytes);
- cbuf->buffer = pipe_user_buffer_create(pipe->screen,
- &shader->constants,
- sizeof(shader->constants));
+ *cbuf = pipe_user_buffer_create(pipe->screen,
+ &shader->constants,
+ sizeof(shader->constants));
}
- ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+ ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf);
}
static VGint blend_bind_samplers(struct vg_context *ctx,
diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c
index 00d23f5c227..c16ac036e3b 100644
--- a/src/gallium/state_trackers/vega/vg_context.c
+++ b/src/gallium/state_trackers/vega/vg_context.c
@@ -122,8 +122,8 @@ struct vg_context * vg_create_context(struct pipe_context *pipe,
void vg_destroy_context(struct vg_context *ctx)
{
- struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf;
- struct pipe_constant_buffer *vsbuf = &ctx->vs_const_buffer;
+ struct pipe_buffer **cbuf = &ctx->mask.cbuf;
+ struct pipe_buffer **vsbuf = &ctx->vs_const_buffer;
util_destroy_blit(ctx->blit);
renderer_destroy(ctx->renderer);
@@ -131,11 +131,11 @@ void vg_destroy_context(struct vg_context *ctx)
shader_destroy(ctx->shader);
paint_destroy(ctx->default_paint);
- if (cbuf && cbuf->buffer)
- pipe_buffer_reference(&cbuf->buffer, NULL);
+ if (*cbuf)
+ pipe_buffer_reference(cbuf, NULL);
- if (vsbuf && vsbuf->buffer)
- pipe_buffer_reference(&vsbuf->buffer, NULL);
+ if (*vsbuf)
+ pipe_buffer_reference(vsbuf, NULL);
if (ctx->clear.fs) {
cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs);
@@ -371,20 +371,20 @@ void vg_validate_state(struct vg_context *ctx)
2.f/fb->width, 2.f/fb->height, 1, 1,
-1, -1, 0, 0
};
- struct pipe_constant_buffer *cbuf = &ctx->vs_const_buffer;
+ struct pipe_buffer **cbuf = &ctx->vs_const_buffer;
vg_set_viewport(ctx, VEGA_Y0_BOTTOM);
- pipe_buffer_reference(&cbuf->buffer, NULL);
- cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 16,
+ pipe_buffer_reference(cbuf, NULL);
+ *cbuf = pipe_buffer_create(ctx->pipe->screen, 16,
PIPE_BUFFER_USAGE_CONSTANT,
param_bytes);
- if (cbuf->buffer) {
- st_no_flush_pipe_buffer_write(ctx, cbuf->buffer,
+ if (*cbuf) {
+ st_no_flush_pipe_buffer_write(ctx, *cbuf,
0, param_bytes, vs_consts);
}
- ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, cbuf);
+ ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, *cbuf);
}
if ((ctx->state.dirty & VS_DIRTY)) {
cso_set_vertex_shader_handle(ctx->cso_context,
diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h
index ccc8889c8c5..ff8c1a04217 100644
--- a/src/gallium/state_trackers/vega/vg_context.h
+++ b/src/gallium/state_trackers/vega/vg_context.h
@@ -113,7 +113,7 @@ struct vg_context
} clear;
struct {
- struct pipe_constant_buffer cbuf;
+ struct pipe_buffer *cbuf;
struct pipe_sampler_state sampler;
struct vg_shader *union_fs;
@@ -135,7 +135,7 @@ struct vg_context
struct pipe_sampler_state blend_sampler;
struct {
- struct pipe_constant_buffer buffer;
+ struct pipe_buffer *buffer;
void *color_matrix_fs;
} filter;
struct vg_paint *default_paint;
@@ -145,7 +145,7 @@ struct vg_context
struct vg_shader *plain_vs;
struct vg_shader *clear_vs;
struct vg_shader *texture_vs;
- struct pipe_constant_buffer vs_const_buffer;
+ struct pipe_buffer *vs_const_buffer;
};
struct vg_object {
diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c
index e5039132758..ff80aab03a3 100644
--- a/src/gallium/state_trackers/vega/vg_tracker.c
+++ b/src/gallium/state_trackers/vega/vg_tracker.c
@@ -36,6 +36,9 @@
#include "util/u_math.h"
#include "util/u_rect.h"
+/* advertise OpenVG support */
+PUBLIC const int st_api_OpenVG = 1;
+
static struct pipe_texture *
create_texture(struct pipe_context *pipe, enum pipe_format format,
VGint width, VGint height)
@@ -368,14 +371,15 @@ void st_unreference_framebuffer(struct st_framebuffer *stfb)
/* FIXME */
}
-void st_make_current(struct vg_context *st,
- struct st_framebuffer *draw,
- struct st_framebuffer *read)
+boolean st_make_current(struct vg_context *st,
+ struct st_framebuffer *draw,
+ struct st_framebuffer *read)
{
vg_set_current_context(st);
if (st) {
st->draw_buffer = draw;
}
+ return VG_TRUE;
}
struct vg_context *st_get_current(void)
@@ -425,3 +429,8 @@ int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level)
{
return 0;
}
+
+st_proc st_get_proc_address(const char *procname)
+{
+ return NULL;
+}
diff --git a/src/gallium/state_trackers/vega/vg_tracker.h b/src/gallium/state_trackers/vega/vg_tracker.h
index 5457631106f..c1196954a76 100644
--- a/src/gallium/state_trackers/vega/vg_tracker.h
+++ b/src/gallium/state_trackers/vega/vg_tracker.h
@@ -45,15 +45,19 @@ struct pipe_fence_handle;
struct pipe_surface;
+PUBLIC
struct vg_context *st_create_context(struct pipe_context *pipe,
const void *visual,
struct vg_context *share);
+PUBLIC
void st_destroy_context( struct vg_context *st );
+PUBLIC
void st_copy_context_state(struct vg_context *dst, struct vg_context *src,
uint mask);
+PUBLIC
struct st_framebuffer *st_create_framebuffer(const void *visual,
enum pipe_format colorFormat,
enum pipe_format depthFormat,
@@ -61,47 +65,63 @@ struct st_framebuffer *st_create_framebuffer(const void *visual,
uint width, uint height,
void *privateData);
+PUBLIC
void st_resize_framebuffer(struct st_framebuffer *stfb,
uint width, uint height);
+PUBLIC
void st_set_framebuffer_surface(struct st_framebuffer *stfb,
uint surfIndex, struct pipe_surface *surf);
+PUBLIC
void st_get_framebuffer_dimensions( struct st_framebuffer *stfb,
uint *width, uint *height);
+PUBLIC
int st_bind_texture_surface(struct pipe_surface *ps, int target, int level,
enum pipe_format format);
+PUBLIC
int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level);
+PUBLIC
int st_get_framebuffer_surface(struct st_framebuffer *stfb,
uint surfIndex, struct pipe_surface **surf);
+PUBLIC
int st_get_framebuffer_texture(struct st_framebuffer *stfb,
uint surfIndex, struct pipe_texture **tex);
+PUBLIC
void *st_framebuffer_private(struct st_framebuffer *stfb);
+PUBLIC
void st_unreference_framebuffer(struct st_framebuffer *stfb);
-void st_make_current(struct vg_context *st,
- struct st_framebuffer *draw,
- struct st_framebuffer *read);
+PUBLIC
+boolean st_make_current(struct vg_context *st,
+ struct st_framebuffer *draw,
+ struct st_framebuffer *read);
+PUBLIC
struct vg_context *st_get_current(void);
+PUBLIC
void st_flush(struct vg_context *st, uint pipeFlushFlags,
struct pipe_fence_handle **fence);
+PUBLIC
void st_finish(struct vg_context *st);
+PUBLIC
void st_notify_swapbuffers(struct st_framebuffer *stfb);
+PUBLIC
void st_notify_swapbuffers_complete(struct st_framebuffer *stfb);
/** Generic function type */
typedef void (*st_proc)();
+PUBLIC
st_proc st_get_proc_address(const char *procname);
#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c
index d80f341e6c2..8f729b565b1 100644
--- a/src/gallium/state_trackers/xorg/xorg_renderer.c
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.c
@@ -379,14 +379,14 @@ struct xorg_renderer * renderer_create(struct pipe_context *pipe)
void renderer_destroy(struct xorg_renderer *r)
{
- struct pipe_constant_buffer *vsbuf = &r->vs_const_buffer;
- struct pipe_constant_buffer *fsbuf = &r->fs_const_buffer;
+ struct pipe_buffer **vsbuf = &r->vs_const_buffer;
+ struct pipe_buffer **fsbuf = &r->fs_const_buffer;
- if (vsbuf && vsbuf->buffer)
- pipe_buffer_reference(&vsbuf->buffer, NULL);
+ if (*vsbuf)
+ pipe_buffer_reference(vsbuf, NULL);
- if (fsbuf && fsbuf->buffer)
- pipe_buffer_reference(&fsbuf->buffer, NULL);
+ if (*fsbuf)
+ pipe_buffer_reference(fsbuf, NULL);
if (r->shaders) {
xorg_shaders_destroy(r->shaders);
@@ -409,20 +409,20 @@ void renderer_set_constants(struct xorg_renderer *r,
const float *params,
int param_bytes)
{
- struct pipe_constant_buffer *cbuf =
+ struct pipe_buffer **cbuf =
(shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer :
&r->fs_const_buffer;
- pipe_buffer_reference(&cbuf->buffer, NULL);
- cbuf->buffer = pipe_buffer_create(r->pipe->screen, 16,
- PIPE_BUFFER_USAGE_CONSTANT,
- param_bytes);
+ pipe_buffer_reference(cbuf, NULL);
+ *cbuf = pipe_buffer_create(r->pipe->screen, 16,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
- if (cbuf->buffer) {
- pipe_buffer_write(r->pipe->screen, cbuf->buffer,
+ if (*cbuf) {
+ pipe_buffer_write(r->pipe->screen, *cbuf,
0, param_bytes, params);
}
- r->pipe->set_constant_buffer(r->pipe, shader_type, 0, cbuf);
+ r->pipe->set_constant_buffer(r->pipe, shader_type, 0, *cbuf);
}
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.h b/src/gallium/state_trackers/xorg/xorg_renderer.h
index 5272cde2b3f..af6aa0567d6 100644
--- a/src/gallium/state_trackers/xorg/xorg_renderer.h
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.h
@@ -23,8 +23,8 @@ struct xorg_renderer {
int fb_width;
int fb_height;
- struct pipe_constant_buffer vs_const_buffer;
- struct pipe_constant_buffer fs_const_buffer;
+ struct pipe_buffer *vs_const_buffer;
+ struct pipe_buffer *fs_const_buffer;
float buffer[BUF_SIZE];
int buffer_size;
diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c
index 6b5a41a3727..5bf0e94b627 100644
--- a/src/gallium/state_trackers/xorg/xorg_xv.c
+++ b/src/gallium/state_trackers/xorg/xorg_xv.c
@@ -486,8 +486,11 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
int dxo, dyo;
Bool hdtv;
int x, y, w, h;
- struct exa_pixmap_priv *dst = exaGetPixmapDriverPrivate(pPixmap);
- struct pipe_surface *dst_surf = xorg_gpu_surface(pPriv->r->pipe->screen, dst);
+ struct exa_pixmap_priv *dst;
+ struct pipe_surface *dst_surf = NULL;
+
+ exaMoveInPixmap(pPixmap);
+ dst = exaGetPixmapDriverPrivate(pPixmap);
if (dst && !dst->tex) {
xorg_exa_set_shared_usage(pPixmap);
@@ -497,6 +500,7 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
if (!dst || !dst->tex)
XORG_FALLBACK("Xv destination %s", !dst ? "!dst" : "!dst->tex");
+ dst_surf = xorg_gpu_surface(pPriv->r->pipe->screen, dst);
hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
REGION_TRANSLATE(pScrn->pScreen, dstRegion, -pPixmap->screen_x,
@@ -516,7 +520,6 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
bind_samplers(pPriv);
setup_fs_video_constants(pPriv->r, hdtv);
- exaMoveInPixmap(pPixmap);
DamageDamageRegion(&pPixmap->drawable, dstRegion);
while (nbox--) {
diff --git a/src/gallium/winsys/drm/Makefile.egl_g3d b/src/gallium/winsys/drm/Makefile.egl_g3d
new file mode 100644
index 00000000000..3ce27258529
--- /dev/null
+++ b/src/gallium/winsys/drm/Makefile.egl_g3d
@@ -0,0 +1,64 @@
+# src/gallium/winsys/drm/Makefile.egl_g3d
+
+# The driver Makefile should define
+#
+# EGL_DRIVER_NAME, the name of the driver
+# EGL_DRIVER_SOURCES, the sources of the driver
+# EGL_DRIVER_LIBS, extra libraries needed by the driver
+# EGL_DRIVER_PIPES, the pipe drivers of the driver
+#
+# before including this file.
+
+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_LIBS = $(common_LIBS) -lX11 -lXext -lXfixes
+
+kms_ST = $(TOP)/src/gallium/state_trackers/egl_g3d/libeglkms.a
+kms_LIBS = $(common_LIBS)
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+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))
+
+default: $(EGL_DISPLAY_LIBS)
+
+$(EGL_DISPLAY_LIBS): $(LIB_GALLIUM_DIR)/%.so: %.so
+ @mkdir -p $(LIB_GALLIUM_DIR)
+ $(INSTALL) $^ $(LIB_GALLIUM_DIR)
+
+define mklib-egl
+$(MKLIB) -noprefix -o $@ $(EGL_DRIVER_OBJECTS) \
+ -Wl,--whole-archive $($(1)_ST) -Wl,--no-whole-archive \
+ $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) $($(1)_LIBS) $(EGL_DRIVER_LIBS)
+endef
+
+egl_x11_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(x11_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile
+ $(call mklib-egl,x11)
+
+egl_kms_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(kms_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile
+ $(call mklib-egl,kms)
+
+clean:
+ -rm -f $(EGL_DRIVER_OBJECTS)
+ -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); \
+ done
+
+depend:
diff --git a/src/gallium/winsys/drm/i965/egl_g3d/Makefile b/src/gallium/winsys/drm/i965/egl_g3d/Makefile
new file mode 100644
index 00000000000..dd2efe24855
--- /dev/null
+++ b/src/gallium/winsys/drm/i965/egl_g3d/Makefile
@@ -0,0 +1,14 @@
+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/egl_g3d/dummy.c b/src/gallium/winsys/drm/i965/egl_g3d/dummy.c
new file mode 100644
index 00000000000..4a1bc28b0b6
--- /dev/null
+++ b/src/gallium/winsys/drm/i965/egl_g3d/dummy.c
@@ -0,0 +1 @@
+/* mklib expects at least one object file */
diff --git a/src/gallium/winsys/drm/i965/gem/i965_drm_api.c b/src/gallium/winsys/drm/i965/gem/i965_drm_api.c
index fc9678d2b62..9a2203fc6d7 100644
--- a/src/gallium/winsys/drm/i965/gem/i965_drm_api.c
+++ b/src/gallium/winsys/drm/i965/gem/i965_drm_api.c
@@ -228,6 +228,7 @@ destroy(struct drm_api *api)
struct drm_api i965_libdrm_api =
{
+ .name = "i965",
.create_context = i965_libdrm_create_context,
.create_screen = i965_libdrm_create_screen,
.texture_from_shared_handle = i965_libdrm_texture_from_shared_handle,
diff --git a/src/gallium/winsys/drm/i965/xorg/Makefile b/src/gallium/winsys/drm/i965/xorg/Makefile
index d91d0006efd..65d521fc1ce 100644
--- a/src/gallium/winsys/drm/i965/xorg/Makefile
+++ b/src/gallium/winsys/drm/i965/xorg/Makefile
@@ -1,19 +1,25 @@
-TARGET = modesetting_drv.so
-CFILES = $(wildcard ./*.c)
-OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES))
TOP = ../../../../../..
-include $(TOP)/configs/current
-INCLUDES = \
- $(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \
- -I../gem \
- -I$(TOP)/src/gallium/include \
- -I$(TOP)/src/gallium/drivers \
- -I$(TOP)/src/gallium/auxiliary \
- -I$(TOP)/src/mesa \
- -I$(TOP)/include \
- -I$(TOP)/src/egl/main
+GALLIUMDIR = $(TOP)/src/gallium
+
+TARGET = i965g_drv.so
+
+CFILES = $(wildcard ./*.c)
+
+include ${TOP}/configs/current
+
+OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES))
+
+CFLAGS = -DHAVE_CONFIG_H \
+ -g -Wall -Wimplicit-function-declaration -fPIC \
+ $(shell pkg-config --cflags pixman-1 xorg-server libdrm xproto) \
+ -I${GALLIUMDIR}/include \
+ -I${GALLIUMDIR}/drivers \
+ -I${GALLIUMDIR}/auxiliary \
+ -I${TOP}/src/mesa \
+ -I$(TOP)/include \
+ -I$(TOP)/src/egl/main
LIBS = \
$(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \
@@ -23,19 +29,20 @@ LIBS = \
$(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
$(GALLIUM_AUXILIARIES)
-DRIVER_DEFINES = \
- -DHAVE_CONFIG_H
-
-
+TARGET_STAGING = $(TOP)/$(LIB_DIR)/gallium/$(TARGET)
#############################################
+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
-all default: $(TARGET)
+$(TOP)/$(LIB_DIR)/gallium:
+ mkdir -p $@
-$(TARGET): $(OBJECTS) Makefile $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a $(LIBS)
- $(TOP)/bin/mklib -noprefix -o $@ \
- $(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_intel
+$(TARGET_STAGING): $(TARGET) $(TOP)/$(LIB_DIR)/gallium
+ $(INSTALL) $(TARGET) $(TOP)/$(LIB_DIR)/gallium
clean:
rm -rf $(OBJECTS) $(TARGET)
@@ -44,14 +51,4 @@ install:
$(INSTALL) -d $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR)
$(MINSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR)
-
-##############################################
-
-
-.c.o:
- $(CC) -c $(CFLAGS) $(INCLUDES) $(DRIVER_DEFINES) $< -o $@
-
-
-##############################################
-
.PHONY = all clean install
diff --git a/src/gallium/winsys/drm/intel/egl_g3d/Makefile b/src/gallium/winsys/drm/intel/egl_g3d/Makefile
new file mode 100644
index 00000000000..cdbb680773c
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/egl_g3d/Makefile
@@ -0,0 +1,14 @@
+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/egl_g3d/dummy.c b/src/gallium/winsys/drm/intel/egl_g3d/dummy.c
new file mode 100644
index 00000000000..4a1bc28b0b6
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/egl_g3d/dummy.c
@@ -0,0 +1 @@
+/* mklib expects at least one object file */
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 5ed2a10af1c..450ae09b345 100644
--- a/src/gallium/winsys/drm/intel/gem/intel_drm_api.c
+++ b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c
@@ -195,6 +195,7 @@ destroy(struct drm_api *api)
struct drm_api intel_drm_api =
{
+ .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 7106a06492d..4b2c6a1025e 100644
--- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c
+++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c
@@ -87,6 +87,7 @@ nouveau_drm_create_screen(struct drm_api *api, int fd,
case 0x60:
init = nv40_screen_create;
break;
+ case 0x50:
case 0x80:
case 0x90:
case 0xa0:
@@ -164,6 +165,7 @@ nouveau_drm_create_context(struct drm_api *api, struct pipe_screen *pscreen)
case 0x60:
init = nv40_create;
break;
+ case 0x50:
case 0x80:
case 0x90:
case 0xa0:
@@ -252,6 +254,7 @@ nouveau_drm_handle_from_pt(struct drm_api *api, struct pipe_screen *pscreen,
}
struct drm_api drm_api_hooks = {
+ .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_g3d/Makefile
new file mode 100644
index 00000000000..865a5d56a97
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/egl_g3d/Makefile
@@ -0,0 +1,19 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+EGL_DRIVER_NAME = nouveau
+EGL_DRIVER_SOURCES = dummy.c
+EGL_DRIVER_LIBS = -ldrm_nouveau
+
+EGL_DRIVER_PIPES = \
+ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \
+ $(TOP)/src/gallium/drivers/nv04/libnv04.a \
+ $(TOP)/src/gallium/drivers/nv10/libnv10.a \
+ $(TOP)/src/gallium/drivers/nv20/libnv20.a \
+ $(TOP)/src/gallium/drivers/nv30/libnv30.a \
+ $(TOP)/src/gallium/drivers/nv40/libnv40.a \
+ $(TOP)/src/gallium/drivers/nv50/libnv50.a \
+ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a
+
+include ../../Makefile.egl_g3d
diff --git a/src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c b/src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c
new file mode 100644
index 00000000000..4a1bc28b0b6
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c
@@ -0,0 +1 @@
+/* mklib expects at least one object file */
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c
index d2367b245a2..385fa857b56 100644
--- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c
+++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c
@@ -146,16 +146,17 @@ static void *radeon_buffer_map(struct pipe_winsys *ws,
(struct radeon_pipe_buffer*)buffer;
int write = 0;
- if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) {
- priv->flush_cb(priv->flush_data);
- }
-
if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) {
uint32_t domain;
if (radeon_bo_is_busy(radeon_buffer->bo, &domain))
return NULL;
}
+
+ if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) {
+ priv->flush_cb(priv->flush_data);
+ }
+
if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) {
write = 1;
}
@@ -280,58 +281,3 @@ struct radeon_winsys* radeon_pipe_winsys(int fd)
return radeon_ws;
}
-#if 0
-static struct pipe_buffer *radeon_buffer_from_handle(struct radeon_screen *radeon_screen,
- uint32_t handle)
-{
- struct radeon_pipe_buffer *radeon_buffer;
- struct radeon_bo *bo = NULL;
-
- bo = radeon_bo_open(radeon_screen->bom, handle, 0, 0, 0, 0);
- if (bo == NULL) {
- return NULL;
- }
- radeon_buffer = calloc(1, sizeof(struct radeon_pipe_buffer));
- if (radeon_buffer == NULL) {
- radeon_bo_unref(bo);
- return NULL;
- }
- pipe_reference_init(&radeon_buffer->base.reference, 1);
- radeon_buffer->base.usage = PIPE_BUFFER_USAGE_PIXEL;
- radeon_buffer->bo = bo;
- return &radeon_buffer->base;
-}
-
-struct pipe_surface *radeon_surface_from_handle(struct radeon_context *radeon_context,
- uint32_t handle,
- enum pipe_format format,
- int w, int h, int pitch)
-{
- struct pipe_screen *pipe_screen = radeon_context->pipe_screen;
- struct pipe_winsys *pipe_winsys = radeon_context->pipe_winsys;
- struct pipe_texture tmpl;
- struct pipe_surface *ps;
- struct pipe_texture *pt;
- struct pipe_buffer *pb;
-
- pb = radeon_buffer_from_handle(radeon_context->radeon_screen, handle);
- if (pb == NULL) {
- return NULL;
- }
- memset(&tmpl, 0, sizeof(tmpl));
- tmpl.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
- tmpl.target = PIPE_TEXTURE_2D;
- tmpl.width0 = w;
- tmpl.height0 = h;
- tmpl.depth0 = 1;
- tmpl.format = format;
-
- pt = pipe_screen->texture_blanket(pipe_screen, &tmpl, &pitch, pb);
- if (pt == NULL) {
- pipe_buffer_reference(&pb, NULL);
- }
- ps = pipe_screen->get_tex_surface(pipe_screen, pt, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_WRITE);
- return ps;
-}
-#endif
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.c b/src/gallium/winsys/drm/radeon/core/radeon_drm.c
index 05194fc52a2..851c2236979 100644
--- a/src/gallium/winsys/drm/radeon/core/radeon_drm.c
+++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.c
@@ -252,6 +252,7 @@ static boolean radeon_local_handle_from_texture(struct drm_api *api,
}
struct drm_api drm_api_hooks = {
+ .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/dri/Makefile b/src/gallium/winsys/drm/radeon/dri/Makefile
index a9889444de8..eaa34180321 100644
--- a/src/gallium/winsys/drm/radeon/dri/Makefile
+++ b/src/gallium/winsys/drm/radeon/dri/Makefile
@@ -2,7 +2,7 @@
TOP = ../../../../../..
include $(TOP)/configs/current
-LIBNAME = radeon_dri.so
+LIBNAME = radeong_dri.so
MINIGLX_SOURCES =
diff --git a/src/gallium/winsys/drm/radeon/egl_g3d/Makefile b/src/gallium/winsys/drm/radeon/egl_g3d/Makefile
new file mode 100644
index 00000000000..9027a5ff46d
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/egl_g3d/Makefile
@@ -0,0 +1,14 @@
+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/radeon/egl_g3d/dummy.c b/src/gallium/winsys/drm/radeon/egl_g3d/dummy.c
new file mode 100644
index 00000000000..4a1bc28b0b6
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/egl_g3d/dummy.c
@@ -0,0 +1 @@
+/* mklib expects at least one object file */
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 5995eee34ba..4f5ccea4677 100644
--- a/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c
+++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c
@@ -358,6 +358,7 @@ static struct dri1_api dri1_api_hooks = {
};
static struct drm_api vmw_drm_api_hooks = {
+ .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/egl_g3d/Makefile b/src/gallium/winsys/drm/vmware/egl_g3d/Makefile
new file mode 100644
index 00000000000..3cf79924e08
--- /dev/null
+++ b/src/gallium/winsys/drm/vmware/egl_g3d/Makefile
@@ -0,0 +1,14 @@
+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/egl_g3d/dummy.c b/src/gallium/winsys/drm/vmware/egl_g3d/dummy.c
new file mode 100644
index 00000000000..4a1bc28b0b6
--- /dev/null
+++ b/src/gallium/winsys/drm/vmware/egl_g3d/dummy.c
@@ -0,0 +1 @@
+/* mklib expects at least one object file */
diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c
index 599973ce127..1d9bac3871c 100644
--- a/src/gallium/winsys/egl_xlib/egl_xlib.c
+++ b/src/gallium/winsys/egl_xlib/egl_xlib.c
@@ -274,7 +274,7 @@ xlib_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy)
static _EGLProc
-xlib_eglGetProcAddress(const char *procname)
+xlib_eglGetProcAddress(_EGLDriver *drv, const char *procname)
{
return (_EGLProc) st_get_proc_address(procname);
}
@@ -751,24 +751,18 @@ xlib_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
static EGLBoolean
xlib_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
{
- /* error checking step: */
- if (!_eglSwapBuffers(drv, dpy, draw))
- return EGL_FALSE;
-
- {
- struct xlib_egl_surface *xsurf = lookup_surface(draw);
- struct pipe_winsys *pws = xsurf->winsys;
- struct pipe_surface *psurf;
+ 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_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
+ &psurf);
- st_notify_swapbuffers(xsurf->Framebuffer);
+ st_notify_swapbuffers(xsurf->Framebuffer);
- display_surface(pws, psurf, xsurf);
+ display_surface(pws, psurf, xsurf);
- check_and_update_buffer_size(xsurf);
- }
+ check_and_update_buffer_size(xsurf);
return EGL_TRUE;
}
diff --git a/src/gallium/winsys/xlib/xlib.c b/src/gallium/winsys/xlib/xlib.c
index 6dbe05f193e..13117712c23 100644
--- a/src/gallium/winsys/xlib/xlib.c
+++ b/src/gallium/winsys/xlib/xlib.c
@@ -47,6 +47,8 @@ enum mode {
MODE_SOFTPIPE
};
+/* advertise OpenGL support */
+PUBLIC const int st_api_OpenGL = 1;
static enum mode get_mode()
{