summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>2010-08-18 14:37:47 +0200
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>2010-08-18 14:37:47 +0200
commit3e54d63429fe7ca5db3c75c181abbaf7a7f55724 (patch)
treee129c36aaef712525f0a04fc5b06c445e3cf84df /src/gallium
parenteaab76457818fad0926b84c663440e8987e1f19f (diff)
parent85d9bc236d6a8ff8f12cbc2150f8c3740354f573 (diff)
Merge remote branch 'origin/master' into nv50-compiler
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/Makefile.template4
-rw-r--r--src/gallium/auxiliary/Makefile2
-rw-r--r--src/gallium/auxiliary/SConscript6
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c11
-rw-r--r--src/gallium/auxiliary/draw/draw_decompose_tmp.h425
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.c42
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.h3
-rw-r--r--src/gallium/auxiliary/draw/draw_gs_tmp.h186
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c24
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe.c206
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_clip.c40
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h7
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c20
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_decompose.h199
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_emit.c1
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c3
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_so_emit.c20
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_util.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h7
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c157
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h209
-rw-r--r--src/gallium/auxiliary/draw/draw_so_emit_tmp.h156
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex.h2
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.c16
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.h3
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_exec.c8
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_llvm.c1
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_sse.c1
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_varient.c6
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.c369
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_assert.c101
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_assert.h (renamed from src/gallium/state_trackers/dri/drm/dri2.h)20
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_conv.c14
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format_aos.c4
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format_soa.c4
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_init.c4
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_init.h2
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_logic.c93
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_logic.h5
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_misc.cpp32
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_pack.c21
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_quad.c4
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c24
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c14
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c52
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.h10
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sanity.c13
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sanity.h3
-rw-r--r--src/gallium/auxiliary/translate/translate.c5
-rw-r--r--src/gallium/auxiliary/translate/translate.h3
-rw-r--r--src/gallium/auxiliary/translate/translate_generic.c155
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c44
-rw-r--r--src/gallium/auxiliary/util/u_blitter.h2
-rw-r--r--src/gallium/auxiliary/util/u_cpu_detect.c70
-rw-r--r--src/gallium/auxiliary/util/u_cpu_detect.h13
-rw-r--r--src/gallium/auxiliary/util/u_debug.c2
-rw-r--r--src/gallium/auxiliary/util/u_draw.h138
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.c2
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.h6
-rw-r--r--src/gallium/auxiliary/util/u_format.h38
-rw-r--r--src/gallium/auxiliary/util/u_format_other.c15
-rw-r--r--src/gallium/auxiliary/util/u_framebuffer.c6
-rw-r--r--src/gallium/auxiliary/util/u_mempool.c6
-rw-r--r--src/gallium/auxiliary/util/u_network.c2
-rw-r--r--src/gallium/auxiliary/util/u_pack_color.h47
-rw-r--r--src/gallium/auxiliary/util/u_prim.h14
-rw-r--r--src/gallium/auxiliary/util/u_split_prim.h105
-rw-r--r--src/gallium/auxiliary/util/u_sse.h30
-rw-r--r--src/gallium/auxiliary/util/u_staging.c95
-rw-r--r--src/gallium/auxiliary/util/u_staging.h37
-rw-r--r--src/gallium/auxiliary/util/u_surfaces.c79
-rw-r--r--src/gallium/auxiliary/util/u_surfaces.h18
-rw-r--r--src/gallium/docs/d3d11ddi.txt30
-rw-r--r--src/gallium/docs/source/conf.py6
-rw-r--r--src/gallium/docs/source/context.rst55
-rw-r--r--src/gallium/docs/source/cso/rasterizer.rst39
-rw-r--r--src/gallium/docs/source/debugging.rst101
-rw-r--r--src/gallium/docs/source/distro.rst9
-rw-r--r--src/gallium/docs/source/exts/formatting.py31
-rw-r--r--src/gallium/docs/source/exts/tgsi.py17
-rw-r--r--src/gallium/docs/source/index.rst1
-rw-r--r--src/gallium/drivers/cell/common.h2
-rw-r--r--src/gallium/drivers/cell/ppu/cell_context.h3
-rw-r--r--src/gallium/drivers/cell/ppu/cell_draw_arrays.c54
-rw-r--r--src/gallium/drivers/cell/ppu/cell_fence.c6
-rw-r--r--src/gallium/drivers/cell/ppu/cell_pipe_state.c2
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_vertex.c22
-rw-r--r--src/gallium/drivers/failover/fo_context.c35
-rw-r--r--src/gallium/drivers/failover/fo_context.h2
-rw-r--r--src/gallium/drivers/failover/fo_state.c18
-rw-r--r--src/gallium/drivers/failover/fo_state_emit.c5
-rw-r--r--src/gallium/drivers/galahad/glhd_context.c101
-rw-r--r--src/gallium/drivers/i915/i915_context.c56
-rw-r--r--src/gallium/drivers/i915/i915_context.h1
-rw-r--r--src/gallium/drivers/i915/i915_state.c14
-rw-r--r--src/gallium/drivers/i965/brw_context.h1
-rw-r--r--src/gallium/drivers/i965/brw_draw.c73
-rw-r--r--src/gallium/drivers/i965/brw_draw_upload.c7
-rw-r--r--src/gallium/drivers/i965/brw_pipe_vertex.c31
-rw-r--r--src/gallium/drivers/identity/id_context.c84
-rw-r--r--src/gallium/drivers/llvmpipe/SConscript3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_depth.c22
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_interp.c17
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.c6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_draw_arrays.c149
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c15
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h5
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_priv.h30
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_tri.c108
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h112
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_tri.c95
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c7
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_vertex.c14
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_blend.c14
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_conv.c14
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_printf.c11
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_round.c12
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_sincos.c18
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tile_soa.py29
-rw-r--r--src/gallium/drivers/nouveau/nouveau_stateobj.h10
-rw-r--r--src/gallium/drivers/nouveau/nouveau_util.h100
-rw-r--r--src/gallium/drivers/nouveau/nouveau_winsys.h5
-rw-r--r--src/gallium/drivers/nv50/nv50_context.c5
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h21
-rw-r--r--src/gallium/drivers/nv50/nv50_push.c8
-rw-r--r--src/gallium/drivers/nv50/nv50_state.c15
-rw-r--r--src/gallium/drivers/nv50/nv50_vbo.c52
-rw-r--r--src/gallium/drivers/nvfx/nvfx_context.c3
-rw-r--r--src/gallium/drivers/nvfx/nvfx_context.h12
-rw-r--r--src/gallium/drivers/nvfx/nvfx_fragprog.c5
-rw-r--r--src/gallium/drivers/nvfx/nvfx_screen.c2
-rw-r--r--src/gallium/drivers/nvfx/nvfx_state.c15
-rw-r--r--src/gallium/drivers/nvfx/nvfx_vbo.c43
-rw-r--r--src/gallium/drivers/nvfx/nvfx_vertprog.c8
-rw-r--r--src/gallium/drivers/r300/Makefile1
-rw-r--r--src/gallium/drivers/r300/SConscript1
-rw-r--r--src/gallium/drivers/r300/r300_blit.c142
-rw-r--r--src/gallium/drivers/r300/r300_chipset.c54
-rw-r--r--src/gallium/drivers/r300/r300_chipset.h14
-rw-r--r--src/gallium/drivers/r300/r300_context.c36
-rw-r--r--src/gallium/drivers/r300/r300_context.h98
-rw-r--r--src/gallium/drivers/r300/r300_cs.h4
-rw-r--r--src/gallium/drivers/r300/r300_debug.c2
-rw-r--r--src/gallium/drivers/r300/r300_defines.h5
-rw-r--r--src/gallium/drivers/r300/r300_emit.c179
-rw-r--r--src/gallium/drivers/r300/r300_emit.h4
-rw-r--r--src/gallium/drivers/r300/r300_flush.c8
-rw-r--r--src/gallium/drivers/r300/r300_fs.c30
-rw-r--r--src/gallium/drivers/r300/r300_hyperz.c259
-rw-r--r--src/gallium/drivers/r300/r300_hyperz.h5
-rw-r--r--src/gallium/drivers/r300/r300_reg.h22
-rw-r--r--src/gallium/drivers/r300/r300_render.c196
-rw-r--r--src/gallium/drivers/r300/r300_render_stencilref.c51
-rw-r--r--src/gallium/drivers/r300/r300_screen.c13
-rw-r--r--src/gallium/drivers/r300/r300_screen.h2
-rw-r--r--src/gallium/drivers/r300/r300_shader_semantics.h2
-rw-r--r--src/gallium/drivers/r300/r300_state.c132
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c163
-rw-r--r--src/gallium/drivers/r300/r300_texture.c598
-rw-r--r--src/gallium/drivers/r300/r300_texture.h9
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.c479
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.h57
-rw-r--r--src/gallium/drivers/r300/r300_tgsi_to_rc.c2
-rw-r--r--src/gallium/drivers/r300/r300_transfer.c49
-rw-r--r--src/gallium/drivers/r300/r300_vs.c5
-rw-r--r--src/gallium/drivers/r300/r300_winsys.h9
-rw-r--r--src/gallium/drivers/r600/Makefile9
-rw-r--r--src/gallium/drivers/r600/SConscript7
-rw-r--r--src/gallium/drivers/r600/r600_asm.c476
-rw-r--r--src/gallium/drivers/r600/r600_asm.h143
-rw-r--r--src/gallium/drivers/r600/r600_blit.c46
-rw-r--r--src/gallium/drivers/r600/r600_buffer.c60
-rw-r--r--src/gallium/drivers/r600/r600_compiler.c447
-rw-r--r--src/gallium/drivers/r600/r600_compiler.h320
-rw-r--r--src/gallium/drivers/r600/r600_compiler_dump.c267
-rw-r--r--src/gallium/drivers/r600/r600_compiler_r600.c972
-rw-r--r--src/gallium/drivers/r600/r600_compiler_r700.c233
-rw-r--r--src/gallium/drivers/r600/r600_compiler_tgsi.c730
-rw-r--r--src/gallium/drivers/r600/r600_context.c179
-rw-r--r--src/gallium/drivers/r600/r600_context.h152
-rw-r--r--src/gallium/drivers/r600/r600_draw.c98
-rw-r--r--src/gallium/drivers/r600/r600_helper.c88
-rw-r--r--src/gallium/drivers/r600/r600_resource.c55
-rw-r--r--src/gallium/drivers/r600/r600_resource.h35
-rw-r--r--src/gallium/drivers/r600/r600_screen.c242
-rw-r--r--src/gallium/drivers/r600/r600_screen.h21
-rw-r--r--src/gallium/drivers/r600/r600_shader.c1375
-rw-r--r--src/gallium/drivers/r600/r600_shader.h246
-rw-r--r--src/gallium/drivers/r600/r600_sq.h20
-rw-r--r--src/gallium/drivers/r600/r600_state.c1506
-rw-r--r--src/gallium/drivers/r600/r600_state_inlines.h311
-rw-r--r--src/gallium/drivers/r600/r600_texture.c432
-rw-r--r--src/gallium/drivers/r600/r600_texture.h53
-rw-r--r--src/gallium/drivers/r600/r600d.h567
-rw-r--r--src/gallium/drivers/r600/r700_asm.c69
-rw-r--r--src/gallium/drivers/r600/radeon.h61
-rw-r--r--src/gallium/drivers/rbug/rbug_context.c94
-rw-r--r--src/gallium/drivers/softpipe/sp_context.c7
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h2
-rw-r--r--src/gallium/drivers/softpipe/sp_draw_arrays.c154
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_fs.c7
-rw-r--r--src/gallium/drivers/softpipe/sp_state.h38
-rw-r--r--src/gallium/drivers/softpipe/sp_state_fs.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_state_vertex.c14
-rw-r--r--src/gallium/drivers/svga/svga_context.h1
-rw-r--r--src/gallium/drivers/svga/svga_pipe_draw.c39
-rw-r--r--src/gallium/drivers/svga/svga_pipe_vertex.c19
-rw-r--r--src/gallium/drivers/trace/tr_context.c116
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.c20
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.h2
-rw-r--r--src/gallium/include/pipe/p_compiler.h10
-rw-r--r--src/gallium/include/pipe/p_context.h45
-rw-r--r--src/gallium/include/pipe/p_state.h35
-rw-r--r--src/gallium/state_trackers/dri/common/dri1_helper.c129
-rw-r--r--src/gallium/state_trackers/dri/common/dri1_helper.h61
-rw-r--r--src/gallium/state_trackers/dri/common/dri_context.h3
-rw-r--r--src/gallium/state_trackers/dri/common/dri_drawable.c74
-rw-r--r--src/gallium/state_trackers/dri/common/dri_drawable.h26
-rw-r--r--src/gallium/state_trackers/dri/common/dri_screen.c53
-rw-r--r--src/gallium/state_trackers/dri/common/dri_screen.h15
-rw-r--r--src/gallium/state_trackers/dri/drm/Makefile1
-rw-r--r--src/gallium/state_trackers/dri/drm/SConscript1
l---------src/gallium/state_trackers/dri/drm/dri1_helper.c1
-rw-r--r--src/gallium/state_trackers/dri/drm/dri2.c155
-rw-r--r--src/gallium/state_trackers/dri/sw/Makefile1
-rw-r--r--src/gallium/state_trackers/dri/sw/SConscript1
l---------src/gallium/state_trackers/dri/sw/dri1_helper.c1
-rw-r--r--src/gallium/state_trackers/dri/sw/drisw.c84
-rw-r--r--src/gallium/state_trackers/dri/sw/drisw.h43
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.c2
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.h12
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_image.c2
-rw-r--r--src/gallium/state_trackers/egl/x11/glxinit.c124
-rw-r--r--src/gallium/state_trackers/egl/x11/glxinit.h19
-rw-r--r--src/gallium/state_trackers/egl/x11/x11_screen.c29
-rw-r--r--src/gallium/state_trackers/python/p_context.i39
-rw-r--r--src/gallium/state_trackers/vega/polygon.c3
-rw-r--r--src/gallium/state_trackers/xorg/xorg_driver.c2
-rw-r--r--src/gallium/targets/Makefile.xorg2
-rw-r--r--src/gallium/targets/dri-i915/Makefile2
-rw-r--r--src/gallium/targets/dri-i965/Makefile11
-rw-r--r--src/gallium/targets/dri-r600/SConscript2
-rw-r--r--src/gallium/targets/egl/st_GL.c1
-rw-r--r--src/gallium/targets/egl/st_GLESv1_CM.c1
-rw-r--r--src/gallium/targets/egl/st_GLESv2.c1
-rw-r--r--src/gallium/tests/graw/SConscript6
-rw-r--r--src/gallium/tests/graw/fs-test.c3
-rw-r--r--src/gallium/tests/graw/gs-test.c5
-rw-r--r--src/gallium/tests/graw/quad-tex.c3
-rw-r--r--src/gallium/tests/graw/tri-gs.c3
-rw-r--r--src/gallium/tests/graw/tri-instanced.c25
-rw-r--r--src/gallium/tests/graw/tri.c3
-rw-r--r--src/gallium/tests/graw/vs-test.c3
-rw-r--r--src/gallium/tests/unit/Makefile3
-rw-r--r--src/gallium/tests/unit/SConscript9
-rw-r--r--src/gallium/tests/unit/translate_test.c310
-rw-r--r--src/gallium/winsys/r600/drm/SConscript25
-rw-r--r--src/gallium/winsys/r600/drm/r600_drm.c5
-rw-r--r--src/gallium/winsys/r600/drm/r600_states.h96
-rw-r--r--src/gallium/winsys/r600/drm/radeon.c1
-rw-r--r--src/gallium/winsys/r600/drm/radeon_ctx.c3
-rw-r--r--src/gallium/winsys/r600/drm/radeon_priv.h30
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm.c38
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_buffer.c2
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_r300.c15
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_winsys.h9
-rw-r--r--src/gallium/winsys/svga/drm/vmw_screen_dri.c2
269 files changed, 10875 insertions, 8369 deletions
diff --git a/src/gallium/Makefile.template b/src/gallium/Makefile.template
index 43203b1756..bff399ec64 100644
--- a/src/gallium/Makefile.template
+++ b/src/gallium/Makefile.template
@@ -23,6 +23,10 @@ INCLUDES = \
-I$(TOP)/src/gallium/drivers \
$(LIBRARY_INCLUDES)
+ifeq ($(MESA_LLVM),1)
+LIBRARY_DEFINES += $(LLVM_CFLAGS)
+endif
+
##### TARGETS #####
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index dcebab7c0f..9544e90a96 100644
--- a/src/gallium/auxiliary/Makefile
+++ b/src/gallium/auxiliary/Makefile
@@ -131,6 +131,7 @@ C_SOURCES = \
util/u_sampler.c \
util/u_simple_shaders.c \
util/u_snprintf.c \
+ util/u_staging.c \
util/u_surface.c \
util/u_surfaces.c \
util/u_texture.c \
@@ -149,6 +150,7 @@ C_SOURCES = \
GALLIVM_SOURCES = \
gallivm/lp_bld_arit.c \
+ gallivm/lp_bld_assert.c \
gallivm/lp_bld_const.c \
gallivm/lp_bld_conv.c \
gallivm/lp_bld_debug.c \
diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript
index 72a16617db..3124e20ce8 100644
--- a/src/gallium/auxiliary/SConscript
+++ b/src/gallium/auxiliary/SConscript
@@ -34,14 +34,14 @@ env.CodeGenerate(
target = 'util/u_format_table.c',
script = '#src/gallium/auxiliary/util/u_format_table.py',
source = ['#src/gallium/auxiliary/util/u_format.csv'],
- command = 'python $SCRIPT $SOURCE > $TARGET'
+ command = python_cmd + ' $SCRIPT $SOURCE > $TARGET'
)
env.CodeGenerate(
target = 'util/u_half.c',
script = 'util/u_half.py',
source = [],
- command = 'python $SCRIPT > $TARGET'
+ command = python_cmd + ' $SCRIPT > $TARGET'
)
env.Depends('util/u_format_table.c', [
@@ -180,6 +180,7 @@ source = [
'util/u_sampler.c',
'util/u_simple_shaders.c',
'util/u_snprintf.c',
+ 'util/u_staging.c',
'util/u_surface.c',
'util/u_surfaces.c',
'util/u_texture.c',
@@ -198,6 +199,7 @@ source = [
if env['llvm']:
source += [
'gallivm/lp_bld_arit.c',
+ 'gallivm/lp_bld_assert.c',
'gallivm/lp_bld_const.c',
'gallivm/lp_bld_conv.c',
'gallivm/lp_bld_debug.c',
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index c127f74188..995b675b9a 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -288,12 +288,19 @@ draw_set_mapped_constant_buffer(struct draw_context *draw,
shader_type == PIPE_SHADER_GEOMETRY);
debug_assert(slot < PIPE_MAX_CONSTANT_BUFFERS);
- if (shader_type == PIPE_SHADER_VERTEX) {
+ switch (shader_type) {
+ case PIPE_SHADER_VERTEX:
draw->pt.user.vs_constants[slot] = buffer;
+ draw->pt.user.vs_constants_size[slot] = size;
draw_vs_set_constants(draw, slot, buffer, size);
- } else if (shader_type == PIPE_SHADER_GEOMETRY) {
+ break;
+ case PIPE_SHADER_GEOMETRY:
draw->pt.user.gs_constants[slot] = buffer;
+ draw->pt.user.gs_constants_size[slot] = size;
draw_gs_set_constants(draw, slot, buffer, size);
+ break;
+ default:
+ assert(0 && "invalid shader type in draw_set_mapped_constant_buffer");
}
}
diff --git a/src/gallium/auxiliary/draw/draw_decompose_tmp.h b/src/gallium/auxiliary/draw/draw_decompose_tmp.h
new file mode 100644
index 0000000000..a52d2b5058
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_decompose_tmp.h
@@ -0,0 +1,425 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.9
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Chia-I Wu <olv@lunarg.com>
+ */
+
+/* these macros are optional */
+#ifndef LOCAL_VARS
+#define LOCAL_VARS
+#endif
+#ifndef FUNC_ENTER
+#define FUNC_ENTER do {} while (0)
+#endif
+#ifndef FUNC_EXIT
+#define FUNC_EXIT do {} while (0)
+#endif
+#ifndef LINE_ADJ
+#define LINE_ADJ(flags, a0, i0, i1, a1) LINE(flags, i0, i1)
+#endif
+#ifndef TRIANGLE_ADJ
+#define TRIANGLE_ADJ(flags, i0, a0, i1, a1, i2, a2) TRIANGLE(flags, i0, i1, i2)
+#endif
+
+static void
+FUNC(FUNC_VARS)
+{
+ unsigned idx[6], i;
+ ushort flags;
+ LOCAL_VARS
+
+ FUNC_ENTER;
+
+ /* prim, count, and last_vertex_last should have been defined */
+ if (0) {
+ debug_printf("%s: prim 0x%x, count %d, last_vertex_last %d\n",
+ __FUNCTION__, prim, count, last_vertex_last);
+ }
+
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < count; i++) {
+ idx[0] = GET_ELT(i);
+ POINT(idx[0]);
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ flags = DRAW_PIPE_RESET_STIPPLE;
+ for (i = 0; i + 1 < count; i += 2) {
+ idx[0] = GET_ELT(i);
+ idx[1] = GET_ELT(i + 1);
+ LINE(flags, idx[0], idx[1]);
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ case PIPE_PRIM_LINE_STRIP:
+ if (count >= 2) {
+ flags = DRAW_PIPE_RESET_STIPPLE;
+ idx[1] = GET_ELT(0);
+ idx[2] = idx[1];
+
+ for (i = 1; i < count; i++, flags = 0) {
+ idx[0] = idx[1];
+ idx[1] = GET_ELT(i);
+ LINE(flags, idx[0], idx[1]);
+ }
+ /* close the loop */
+ if (prim == PIPE_PRIM_LINE_LOOP)
+ LINE(flags, idx[1], idx[2]);
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
+ for (i = 0; i + 2 < count; i += 3) {
+ idx[0] = GET_ELT(i);
+ idx[1] = GET_ELT(i + 1);
+ idx[2] = GET_ELT(i + 2);
+ TRIANGLE(flags, idx[0], idx[1], idx[2]);
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ if (count >= 3) {
+ flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
+ idx[1] = GET_ELT(0);
+ idx[2] = GET_ELT(1);
+
+ if (last_vertex_last) {
+ for (i = 0; i + 2 < count; i++) {
+ idx[0] = idx[1];
+ idx[1] = idx[2];
+ idx[2] = GET_ELT(i + 2);
+ /* always emit idx[2] last */
+ if (i & 1)
+ TRIANGLE(flags, idx[1], idx[0], idx[2]);
+ else
+ TRIANGLE(flags, idx[0], idx[1], idx[2]);
+ }
+ }
+ else {
+ for (i = 0; i + 2 < count; i++) {
+ idx[0] = idx[1];
+ idx[1] = idx[2];
+ idx[2] = GET_ELT(i + 2);
+ /* always emit idx[0] first */
+ if (i & 1)
+ TRIANGLE(flags, idx[0], idx[2], idx[1]);
+ else
+ TRIANGLE(flags, idx[0], idx[1], idx[2]);
+ }
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (count >= 3) {
+ flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
+ idx[0] = GET_ELT(0);
+ idx[2] = GET_ELT(1);
+
+ /* idx[0] is neither the first nor the last vertex */
+ if (last_vertex_last) {
+ for (i = 0; i + 2 < count; i++) {
+ idx[1] = idx[2];
+ idx[2] = GET_ELT(i + 2);
+ /* always emit idx[2] last */
+ TRIANGLE(flags, idx[0], idx[1], idx[2]);
+ }
+ }
+ else {
+ for (i = 0; i + 2 < count; i++) {
+ idx[1] = idx[2];
+ idx[2] = GET_ELT(i + 2);
+ /* always emit idx[1] first */
+ TRIANGLE(flags, idx[1], idx[2], idx[0]);
+ }
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUADS:
+ if (last_vertex_last) {
+ for (i = 0; i + 3 < count; i += 4) {
+ idx[0] = GET_ELT(i);
+ idx[1] = GET_ELT(i + 1);
+ idx[2] = GET_ELT(i + 2);
+ idx[3] = GET_ELT(i + 3);
+
+ flags = DRAW_PIPE_RESET_STIPPLE |
+ DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_2;
+ /* always emit idx[3] last */
+ TRIANGLE(flags, idx[0], idx[1], idx[3]);
+
+ flags = DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_1;
+ TRIANGLE(flags, idx[1], idx[2], idx[3]);
+ }
+ }
+ else {
+ for (i = 0; i + 3 < count; i += 4) {
+ idx[0] = GET_ELT(i);
+ idx[1] = GET_ELT(i + 1);
+ idx[2] = GET_ELT(i + 2);
+ idx[3] = GET_ELT(i + 3);
+
+ flags = DRAW_PIPE_RESET_STIPPLE |
+ DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_1;
+ /* XXX should always emit idx[0] first */
+ /* always emit idx[3] first */
+ TRIANGLE(flags, idx[3], idx[0], idx[1]);
+
+ flags = DRAW_PIPE_EDGE_FLAG_1 |
+ DRAW_PIPE_EDGE_FLAG_2;
+ TRIANGLE(flags, idx[3], idx[1], idx[2]);
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ if (count >= 4) {
+ idx[2] = GET_ELT(0);
+ idx[3] = GET_ELT(1);
+
+ if (last_vertex_last) {
+ for (i = 0; i + 3 < count; i += 2) {
+ idx[0] = idx[2];
+ idx[1] = idx[3];
+ idx[2] = GET_ELT(i + 2);
+ idx[3] = GET_ELT(i + 3);
+
+ /* always emit idx[3] last */
+ flags = DRAW_PIPE_RESET_STIPPLE |
+ DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_2;
+ TRIANGLE(flags, idx[2], idx[0], idx[3]);
+
+ flags = DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_1;
+ TRIANGLE(flags, idx[0], idx[1], idx[3]);
+ }
+ }
+ else {
+ for (i = 0; i + 3 < count; i += 2) {
+ idx[0] = idx[2];
+ idx[1] = idx[3];
+ idx[2] = GET_ELT(i + 2);
+ idx[3] = GET_ELT(i + 3);
+
+ flags = DRAW_PIPE_RESET_STIPPLE |
+ DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_1;
+ /* XXX should always emit idx[0] first */
+ /* always emit idx[3] first */
+ TRIANGLE(flags, idx[3], idx[2], idx[0]);
+
+ flags = DRAW_PIPE_EDGE_FLAG_1 |
+ DRAW_PIPE_EDGE_FLAG_2;
+ TRIANGLE(flags, idx[3], idx[0], idx[1]);
+ }
+ }
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ if (count >= 3) {
+ ushort edge_next, edge_finish;
+
+ if (last_vertex_last) {
+ flags = (DRAW_PIPE_RESET_STIPPLE |
+ DRAW_PIPE_EDGE_FLAG_2 |
+ DRAW_PIPE_EDGE_FLAG_0);
+ edge_next = DRAW_PIPE_EDGE_FLAG_0;
+ edge_finish = DRAW_PIPE_EDGE_FLAG_1;
+ }
+ else {
+ flags = (DRAW_PIPE_RESET_STIPPLE |
+ DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_1);
+ edge_next = DRAW_PIPE_EDGE_FLAG_1;
+ edge_finish = DRAW_PIPE_EDGE_FLAG_2;
+ }
+
+ idx[0] = GET_ELT(0);
+ idx[2] = GET_ELT(1);
+
+ for (i = 0; i + 2 < count; i++, flags = edge_next) {
+ idx[1] = idx[2];
+ idx[2] = GET_ELT(i + 2);
+
+ if (i + 3 == count)
+ flags |= edge_finish;
+
+ /* idx[0] is both the first and the last vertex */
+ if (last_vertex_last)
+ TRIANGLE(flags, idx[1], idx[2], idx[0]);
+ else
+ TRIANGLE(flags, idx[0], idx[1], idx[2]);
+ }
+ }
+ break;
+
+ case PIPE_PRIM_LINES_ADJACENCY:
+ flags = DRAW_PIPE_RESET_STIPPLE;
+ for (i = 0; i + 3 < count; i += 4) {
+ idx[0] = GET_ELT(i);
+ idx[1] = GET_ELT(i + 1);
+ idx[2] = GET_ELT(i + 2);
+ idx[3] = GET_ELT(i + 3);
+ LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+ if (count >= 4) {
+ flags = DRAW_PIPE_RESET_STIPPLE;
+ idx[1] = GET_ELT(0);
+ idx[2] = GET_ELT(1);
+ idx[3] = GET_ELT(2);
+
+ for (i = 1; i + 2 < count; i++, flags = 0) {
+ idx[0] = idx[1];
+ idx[1] = idx[2];
+ idx[2] = idx[3];
+ idx[3] = GET_ELT(i + 2);
+ LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES_ADJACENCY:
+ flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
+ for (i = 0; i + 5 < count; i += 6) {
+ idx[0] = GET_ELT(i);
+ idx[1] = GET_ELT(i + 1);
+ idx[2] = GET_ELT(i + 2);
+ idx[3] = GET_ELT(i + 3);
+ idx[4] = GET_ELT(i + 4);
+ idx[5] = GET_ELT(i + 5);
+ TRIANGLE_ADJ(flags, idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+ if (count >= 6) {
+ flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
+ idx[0] = GET_ELT(1);
+ idx[2] = GET_ELT(0);
+ idx[4] = GET_ELT(2);
+ idx[3] = GET_ELT(4);
+
+ /*
+ * The vertices of the i-th triangle are stored in
+ * idx[0,2,4] = { 2*i, 2*i+2, 2*i+4 };
+ *
+ * The adjacent vertices are stored in
+ * idx[1,3,5] = { 2*i-2, 2*i+6, 2*i+3 }.
+ *
+ * However, there are two exceptions:
+ *
+ * For the first triangle, idx[1] = 1;
+ * For the last triangle, idx[3] = 2*i+5.
+ */
+ if (last_vertex_last) {
+ for (i = 0; i + 5 < count; i += 2) {
+ idx[1] = idx[0];
+
+ idx[0] = idx[2];
+ idx[2] = idx[4];
+ idx[4] = idx[3];
+
+ idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
+ idx[5] = GET_ELT(i + 3);
+
+ /*
+ * alternate the first two vertices (idx[0] and idx[2]) and the
+ * corresponding adjacent vertices (idx[3] and idx[5]) to have
+ * the correct orientation
+ */
+ if (i & 2) {
+ TRIANGLE_ADJ(flags,
+ idx[2], idx[1], idx[0], idx[5], idx[4], idx[3]);
+ }
+ else {
+ TRIANGLE_ADJ(flags,
+ idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
+ }
+ }
+ }
+ else {
+ for (i = 0; i + 5 < count; i += 2) {
+ idx[1] = idx[0];
+
+ idx[0] = idx[2];
+ idx[2] = idx[4];
+ idx[4] = idx[3];
+
+ idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
+ idx[5] = GET_ELT(i + 3);
+
+ /*
+ * alternate the last two vertices (idx[2] and idx[4]) and the
+ * corresponding adjacent vertices (idx[1] and idx[5]) to have
+ * the correct orientation
+ */
+ if (i & 2) {
+ TRIANGLE_ADJ(flags,
+ idx[0], idx[5], idx[4], idx[3], idx[2], idx[1]);
+ }
+ else {
+ TRIANGLE_ADJ(flags,
+ idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ FUNC_EXIT;
+}
+
+#undef LOCAL_VARS
+#undef FUNC_ENTER
+#undef FUNC_EXIT
+#undef LINE_ADJ
+#undef TRIANGLE_ADJ
+
+#undef FUNC
+#undef FUNC_VARS
+#undef GET_ELT
+#undef POINT
+#undef LINE
+#undef TRIANGLE
diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
index 79a57a67f3..4a1013e79a 100644
--- a/src/gallium/auxiliary/draw/draw_gs.c
+++ b/src/gallium/auxiliary/draw/draw_gs.c
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright 2009 VMWare Inc.
+ * Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -75,7 +75,10 @@ draw_gs_set_constants(struct draw_context *draw,
const void *constants,
unsigned size)
{
- /* noop */
+ /* noop. added here for symmetry with the VS
+ * code and in case we'll ever want to allign
+ * the constants, e.g. when we'll change to a
+ * different interpreter */
}
@@ -370,32 +373,23 @@ static void gs_tri_adj(struct draw_geometry_shader *shader,
gs_flush(shader, 1);
}
-#define TRIANGLE(gs,i0,i1,i2) gs_tri(gs,i0,i1,i2)
-#define TRI_ADJ(gs,i0,i1,i2,i3,i4,i5) gs_tri_adj(gs,i0,i1,i2,i3,i4,i5)
-#define LINE(gs,i0,i1) gs_line(gs,i0,i1)
-#define LINE_ADJ(gs,i0,i1,i2,i3) gs_line_adj(gs,i0,i1,i2,i3)
-#define POINT(gs,i0) gs_point(gs,i0)
-#define FUNC gs_run
-#define LOCAL_VARS
+#define FUNC gs_run
+#define GET_ELT(idx) (idx)
#include "draw_gs_tmp.h"
-#define TRIANGLE(gs,i0,i1,i2) gs_tri(gs,elts[i0],elts[i1],elts[i2])
-#define TRI_ADJ(gs,i0,i1,i2,i3,i4,i5) \
- gs_tri_adj(gs,elts[i0],elts[i1],elts[i2],elts[i3], \
- elts[i4],elts[i5])
-#define LINE(gs,i0,i1) gs_line(gs,elts[i0],elts[i1])
-#define LINE_ADJ(gs,i0,i1,i2,i3) gs_line_adj(gs,elts[i0], \
- elts[i1], \
- elts[i2],elts[i3])
-#define POINT(gs,i0) gs_point(gs,elts[i0])
-#define FUNC gs_run_elts
-#define LOCAL_VARS \
- const ushort *elts = input_prims->elts;
+#define FUNC gs_run_elts
+#define LOCAL_VARS const ushort *elts = input_prims->elts;
+#define GET_ELT(idx) (elts[idx] & ~DRAW_PIPE_FLAG_MASK)
#include "draw_gs_tmp.h"
+
+/**
+ * Execute geometry shader using TGSI interpreter.
+ */
int draw_geometry_shader_run(struct draw_geometry_shader *shader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
const struct draw_vertex_info *input_verts,
const struct draw_prim_info *input_prim,
struct draw_vertex_info *output_verts,
@@ -405,7 +399,6 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
unsigned input_stride = input_verts->vertex_size;
unsigned vertex_size = input_verts->vertex_size;
struct tgsi_exec_machine *machine = shader->machine;
- unsigned int i;
unsigned num_input_verts = input_prim->linear ?
input_verts->count :
input_prim->count;
@@ -447,9 +440,8 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
}
shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned));
- for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
- machine->Consts[i] = constants[i];
- }
+ tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
+ constants, constants_size);
if (input_prim->linear)
gs_run(shader, input_prim, input_verts,
diff --git a/src/gallium/auxiliary/draw/draw_gs.h b/src/gallium/auxiliary/draw/draw_gs.h
index 2cb634818c..67bc1aa73f 100644
--- a/src/gallium/auxiliary/draw/draw_gs.h
+++ b/src/gallium/auxiliary/draw/draw_gs.h
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright 2009 VMWare Inc.
+ * Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -73,6 +73,7 @@ struct draw_geometry_shader {
*/
int draw_geometry_shader_run(struct draw_geometry_shader *shader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
const struct draw_vertex_info *input_verts,
const struct draw_prim_info *input_prim,
struct draw_vertex_info *output_verts,
diff --git a/src/gallium/auxiliary/draw/draw_gs_tmp.h b/src/gallium/auxiliary/draw/draw_gs_tmp.h
index 7a8683cf7c..4a17af0dea 100644
--- a/src/gallium/auxiliary/draw/draw_gs_tmp.h
+++ b/src/gallium/auxiliary/draw/draw_gs_tmp.h
@@ -1,152 +1,34 @@
-
-static void FUNC( struct draw_geometry_shader *shader,
- const struct draw_prim_info *input_prims,
- const struct draw_vertex_info *input_verts,
- struct draw_prim_info *output_prims,
- struct draw_vertex_info *output_verts)
-{
- struct draw_context *draw = shader->draw;
-
- boolean flatfirst = (draw->rasterizer->flatshade &&
- draw->rasterizer->flatshade_first);
- unsigned i, j;
- unsigned count = input_prims->count;
- LOCAL_VARS
-
- if (0) debug_printf("%s %d\n", __FUNCTION__, count);
-
- debug_assert(input_prims->primitive_count == 1);
-
- switch (input_prims->prim) {
- case PIPE_PRIM_POINTS:
- for (i = 0; i < count; i++) {
- POINT( shader, i + 0 );
- }
- break;
-
- case PIPE_PRIM_LINES:
- for (i = 0; i+1 < count; i += 2) {
- LINE( shader , i + 0 , i + 1 );
- }
- break;
-
- case PIPE_PRIM_LINE_LOOP:
- if (count >= 2) {
-
- for (i = 1; i < count; i++) {
- LINE( shader, i - 1, i );
- }
-
- LINE( shader, i - 1, 0 );
- }
- break;
-
- case PIPE_PRIM_LINE_STRIP:
- for (i = 1; i < count; i++) {
- LINE( shader, i - 1, i );
- }
- break;
-
- case PIPE_PRIM_TRIANGLES:
- for (i = 0; i+2 < count; i += 3) {
- TRIANGLE( shader, i + 0, i + 1, i + 2 );
- }
- break;
-
- case PIPE_PRIM_TRIANGLE_STRIP:
- if (flatfirst) {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( shader,
- i + 0,
- i + 1 + (i&1),
- i + 2 - (i&1) );
- }
- }
- else {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( shader,
- i + 0 + (i&1),
- i + 1 - (i&1),
- i + 2 );
- }
- }
- break;
-
- case PIPE_PRIM_TRIANGLE_FAN:
- if (count >= 3) {
- if (flatfirst) {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( shader,
- i + 1,
- i + 2,
- 0 );
- }
- }
- else {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( shader,
- 0,
- i + 1,
- i + 2 );
- }
- }
- }
- break;
-
- case PIPE_PRIM_POLYGON:
- {
- for (i = 0; i+2 < count; i++) {
-
- if (flatfirst) {
- TRIANGLE( shader, 0, i + 1, i + 2 );
- }
- else {
- TRIANGLE( shader, i + 1, i + 2, 0 );
- }
- }
- }
- break;
-
- case PIPE_PRIM_LINES_ADJACENCY:
- for (i = 0; i+3 < count; i += 4) {
- LINE_ADJ( shader , i + 0 , i + 1, i + 2, i + 3 );
- }
- break;
- case PIPE_PRIM_LINE_STRIP_ADJACENCY:
- for (i = 1; i + 2 < count; i++) {
- LINE_ADJ( shader, i - 1, i, i + 1, i + 2 );
- }
- break;
-
- case PIPE_PRIM_TRIANGLES_ADJACENCY:
- for (i = 0; i+5 < count; i += 5) {
- TRI_ADJ( shader, i + 0, i + 1, i + 2,
- i + 3, i + 4, i + 5);
- }
- break;
- case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
- for (i = 0, j = 0; i+5 < count; i += 2, ++j) {
- TRI_ADJ( shader,
- i + 0,
- i + 1 + 2*(j&1),
- i + 2 + 2*(j&1),
- i + 3 - 2*(j&1),
- i + 4 - 2*(j&1),
- i + 5);
- }
- break;
-
- default:
- debug_assert(!"Unsupported primitive in geometry shader");
- break;
- }
-}
-
-
-#undef TRIANGLE
-#undef TRI_ADJ
-#undef POINT
-#undef LINE
-#undef LINE_ADJ
-#undef FUNC
-#undef LOCAL_VARS
+#define FUNC_VARS struct draw_geometry_shader *gs, \
+ const struct draw_prim_info *input_prims, \
+ const struct draw_vertex_info *input_verts, \
+ struct draw_prim_info *output_prims, \
+ struct draw_vertex_info *output_verts
+
+#define FUNC_ENTER \
+ /* declare more local vars */ \
+ struct draw_context *draw = gs->draw; \
+ const unsigned prim = input_prims->prim; \
+ const unsigned count = input_prims->count; \
+ const boolean last_vertex_last = \
+ !(draw->rasterizer->flatshade && \
+ draw->rasterizer->flatshade_first); \
+ do { \
+ debug_assert(input_prims->primitive_count == 1); \
+ switch (prim) { \
+ case PIPE_PRIM_QUADS: \
+ case PIPE_PRIM_QUAD_STRIP: \
+ case PIPE_PRIM_POLYGON: \
+ debug_assert(!"unexpected primitive type in GS"); \
+ return; \
+ default: \
+ break; \
+ } \
+ } while (0) \
+
+#define POINT(i0) gs_point(gs,i0)
+#define LINE(flags,i0,i1) gs_line(gs,i0,i1)
+#define TRIANGLE(flags,i0,i1,i2) gs_tri(gs,i0,i1,i2)
+#define LINE_ADJ(flags,i0,i1,i2,i3) gs_line_adj(gs,i0,i1,i2,i3)
+#define TRIANGLE_ADJ(flags,i0,i1,i2,i3,i4,i5) gs_tri_adj(gs,i0,i1,i2,i3,i4,i5)
+
+#include "draw_decompose_tmp.h"
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 19f96c37ab..8d53601d19 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -37,6 +37,8 @@
#include "gallivm/lp_bld_debug.h"
#include "gallivm/lp_bld_tgsi.h"
#include "gallivm/lp_bld_printf.h"
+#include "gallivm/lp_bld_intr.h"
+#include "gallivm/lp_bld_init.h"
#include "tgsi/tgsi_exec.h"
#include "tgsi/tgsi_dump.h"
@@ -681,7 +683,6 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
unsigned i, j;
struct lp_build_context bld;
struct lp_build_loop_state lp_loop;
- struct lp_type vs_type = lp_type_float_vec(32);
const int max_vertices = 4;
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
void *code;
@@ -730,7 +731,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
builder = LLVMCreateBuilder();
LLVMPositionBuilderAtEnd(builder, block);
- lp_build_context_init(&bld, builder, vs_type);
+ lp_build_context_init(&bld, builder, lp_type_int(32));
end = lp_build_add(&bld, start, count);
@@ -793,6 +794,11 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
sampler->destroy(sampler);
+#ifdef PIPE_ARCH_X86
+ /* Avoid corrupting the FPU stack on 32bit OSes. */
+ lp_build_intrinsic(builder, "llvm.x86.mmx.emms", LLVMVoidType(), NULL, 0);
+#endif
+
LLVMBuildRetVoid(builder);
LLVMDisposeBuilder(builder);
@@ -820,6 +826,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
if (gallivm_debug & GALLIVM_DEBUG_ASM) {
lp_disassemble(code);
}
+ lp_func_delete_body(variant->function);
}
@@ -837,9 +844,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
struct draw_context *draw = llvm->draw;
unsigned i, j;
struct lp_build_context bld;
- struct lp_build_context bld_int;
struct lp_build_loop_state lp_loop;
- struct lp_type vs_type = lp_type_float_vec(32);
const int max_vertices = 4;
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
LLVMValueRef fetch_max;
@@ -891,8 +896,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
builder = LLVMCreateBuilder();
LLVMPositionBuilderAtEnd(builder, block);
- lp_build_context_init(&bld, builder, vs_type);
- lp_build_context_init(&bld_int, builder, lp_type_int(32));
+ lp_build_context_init(&bld, builder, lp_type_int(32));
step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0);
@@ -927,7 +931,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
/* make sure we're not out of bounds which can happen
* if fetch_count % 4 != 0, because on the last iteration
* a few of the 4 vertex fetches will be out of bounds */
- true_index = lp_build_min(&bld_int, true_index, fetch_max);
+ true_index = lp_build_min(&bld, true_index, fetch_max);
fetch_ptr = LLVMBuildGEP(builder, fetch_elts,
&true_index, 1, "");
@@ -963,6 +967,11 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
sampler->destroy(sampler);
+#ifdef PIPE_ARCH_X86
+ /* Avoid corrupting the FPU stack on 32bit OSes. */
+ lp_build_intrinsic(builder, "llvm.x86.mmx.emms", LLVMVoidType(), NULL, 0);
+#endif
+
LLVMBuildRetVoid(builder);
LLVMDisposeBuilder(builder);
@@ -990,6 +999,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
if (gallivm_debug & GALLIVM_DEBUG_ASM) {
lp_disassemble(code);
}
+ lp_func_delete_body(variant->function_elts);
}
void
diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c
index 8cd75ecf9a..58995e0724 100644
--- a/src/gallium/auxiliary/draw/draw_pipe.c
+++ b/src/gallium/auxiliary/draw/draw_pipe.c
@@ -169,77 +169,50 @@ static void do_triangle( struct draw_context *draw,
/*
* Set up macros for draw_pt_decompose.h template code.
* This code uses vertex indexes / elements.
+ *
+ * Flags are needed by the stipple and unfilled stages. When the two stages
+ * are active, vcache_run_extras is called and the flags are stored in the
+ * higher bits of i0. Otherwise, flags do not matter.
*/
-/* emit first quad vertex as first vertex in triangles */
-#define QUAD_FIRST_PV(i0,i1,i2,i3) \
- do_triangle( draw, \
- ( DRAW_PIPE_RESET_STIPPLE | \
- DRAW_PIPE_EDGE_FLAG_0 | \
- DRAW_PIPE_EDGE_FLAG_1 ), \
- verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK)); \
- do_triangle( draw, \
- ( DRAW_PIPE_EDGE_FLAG_1 | \
- DRAW_PIPE_EDGE_FLAG_2 ), \
- verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK))
-
-/* emit last quad vertex as last vertex in triangles */
-#define QUAD_LAST_PV(i0,i1,i2,i3) \
- do_triangle( draw, \
- ( DRAW_PIPE_RESET_STIPPLE | \
- DRAW_PIPE_EDGE_FLAG_0 | \
- DRAW_PIPE_EDGE_FLAG_2 ), \
- verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK)); \
- do_triangle( draw, \
- ( DRAW_PIPE_EDGE_FLAG_0 | \
- DRAW_PIPE_EDGE_FLAG_1 ), \
- verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK))
-
-#define TRIANGLE(flags,i0,i1,i2) \
- do_triangle( draw, \
- elts[i0], /* flags */ \
- verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK) );
-
-#define LINE(flags,i0,i1) \
- do_line( draw, \
- elts[i0], \
- verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK) );
+#define TRIANGLE(flags,i0,i1,i2) \
+ do { \
+ assert(!((i1) & DRAW_PIPE_FLAG_MASK)); \
+ assert(!((i2) & DRAW_PIPE_FLAG_MASK)); \
+ do_triangle( draw, \
+ i0, /* flags */ \
+ verts + stride * (i0 & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i1), \
+ verts + stride * (i2) ); \
+ } while (0)
+
+#define LINE(flags,i0,i1) \
+ do { \
+ assert(!((i1) & DRAW_PIPE_FLAG_MASK)); \
+ do_line( draw, \
+ i0, /* flags */ \
+ verts + stride * (i0 & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i1) ); \
+ } while (0)
#define POINT(i0) \
- do_point( draw, \
- verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK) )
+ do { \
+ assert(!((i0) & DRAW_PIPE_FLAG_MASK)); \
+ do_point( draw, verts + stride * (i0) ); \
+ } while (0)
+
+#define GET_ELT(idx) (elts[idx])
-#define FUNC pipe_run
-#define ARGS \
+#define FUNC pipe_run_elts
+#define FUNC_VARS \
struct draw_context *draw, \
unsigned prim, \
struct vertex_header *vertices, \
unsigned stride, \
- const ushort *elts
-
-#define LOCAL_VARS \
- char *verts = (char *)vertices; \
- boolean flatfirst = (draw->rasterizer->flatshade && \
- draw->rasterizer->flatshade_first); \
- unsigned i; \
- ushort flags
-
-#define FLUSH
+ const ushort *elts, \
+ unsigned count
#include "draw_pt_decompose.h"
-#undef ARGS
-#undef LOCAL_VARS
@@ -269,14 +242,29 @@ void draw_pipeline_run( struct draw_context *draw,
i < prim_info->primitive_count;
start += prim_info->primitive_lengths[i], i++)
{
- unsigned count = prim_info->primitive_lengths[i];
-
- pipe_run(draw,
- prim_info->prim,
- vert_info->verts,
- vert_info->stride,
- prim_info->elts + start,
- count);
+ const unsigned count = prim_info->primitive_lengths[i];
+
+#if DEBUG
+ /* make sure none of the element indexes go outside the vertex buffer */
+ {
+ unsigned max_index = 0x0, i;
+ /* find the largest element index */
+ for (i = 0; i < count; i++) {
+ unsigned int index = (prim_info->elts[start + i]
+ & ~DRAW_PIPE_FLAG_MASK);
+ if (index > max_index)
+ max_index = index;
+ }
+ assert(max_index <= vert_info->count);
+ }
+#endif
+
+ pipe_run_elts(draw,
+ prim_info->prim,
+ vert_info->verts,
+ vert_info->stride,
+ prim_info->elts + start,
+ count);
}
draw->pipeline.verts = NULL;
@@ -289,70 +277,30 @@ void draw_pipeline_run( struct draw_context *draw,
* This code is for non-indexed (aka linear) rendering (no elts).
*/
-/* emit first quad vertex as first vertex in triangles */
-#define QUAD_FIRST_PV(i0,i1,i2,i3) \
- do_triangle( draw, \
- ( DRAW_PIPE_RESET_STIPPLE | \
- DRAW_PIPE_EDGE_FLAG_0 | \
- DRAW_PIPE_EDGE_FLAG_1 ), \
- verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK)); \
- do_triangle( draw, \
- ( DRAW_PIPE_EDGE_FLAG_1 | \
- DRAW_PIPE_EDGE_FLAG_2 ), \
- verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK))
-
-/* emit last quad vertex as last vertex in triangles */
-#define QUAD_LAST_PV(i0,i1,i2,i3) \
- do_triangle( draw, \
- ( DRAW_PIPE_RESET_STIPPLE | \
- DRAW_PIPE_EDGE_FLAG_0 | \
- DRAW_PIPE_EDGE_FLAG_2 ), \
- verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK)); \
- do_triangle( draw, \
- ( DRAW_PIPE_EDGE_FLAG_0 | \
- DRAW_PIPE_EDGE_FLAG_1 ), \
- verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK))
-
-#define TRIANGLE(flags,i0,i1,i2) \
- do_triangle( draw, \
- flags, /* flags */ \
- verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK))
-
-#define LINE(flags,i0,i1) \
- do_line( draw, \
- flags, \
- verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
- verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK))
+#define TRIANGLE(flags,i0,i1,i2) \
+ do_triangle( draw, flags, \
+ verts + stride * (i0), \
+ verts + stride * (i1), \
+ verts + stride * (i2) )
-#define POINT(i0) \
- do_point( draw, \
- verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK) )
+#define LINE(flags,i0,i1) \
+ do_line( draw, flags, \
+ verts + stride * (i0), \
+ verts + stride * (i1) )
-#define FUNC pipe_run_linear
-#define ARGS \
- struct draw_context *draw, \
- unsigned prim, \
- struct vertex_header *vertices, \
- unsigned stride
+#define POINT(i0) \
+ do_point( draw, verts + stride * (i0) )
-#define LOCAL_VARS \
- char *verts = (char *)vertices; \
- boolean flatfirst = (draw->rasterizer->flatshade && \
- draw->rasterizer->flatshade_first); \
- unsigned i; \
- ushort flags
-#define FLUSH
+#define GET_ELT(idx) (idx)
+
+#define FUNC pipe_run_linear
+#define FUNC_VARS \
+ struct draw_context *draw, \
+ unsigned prim, \
+ struct vertex_header *vertices, \
+ unsigned stride, \
+ unsigned count
#include "draw_pt_decompose.h"
@@ -378,6 +326,8 @@ void draw_pipeline_run_linear( struct draw_context *draw,
draw->pipeline.vertex_stride = vert_info->stride;
draw->pipeline.vertex_count = count;
+ assert(count <= vert_info->count);
+
pipe_run_linear(draw,
prim_info->prim,
(struct vertex_header*)verts,
diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c
index 1cf6ee7a7f..8a3d499feb 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_clip.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c
@@ -68,8 +68,7 @@ struct clip_stage {
};
-/* This is a bit confusing:
- */
+/** Cast wrapper */
static INLINE struct clip_stage *clip_stage( struct draw_stage *stage )
{
return (struct clip_stage *)stage;
@@ -81,18 +80,22 @@ static INLINE struct clip_stage *clip_stage( struct draw_stage *stage )
/* All attributes are float[4], so this is easy:
*/
-static void interp_attr( float *fdst,
+static void interp_attr( float dst[4],
float t,
- const float *fin,
- const float *fout )
+ const float in[4],
+ const float out[4] )
{
- fdst[0] = LINTERP( t, fout[0], fin[0] );
- fdst[1] = LINTERP( t, fout[1], fin[1] );
- fdst[2] = LINTERP( t, fout[2], fin[2] );
- fdst[3] = LINTERP( t, fout[3], fin[3] );
+ dst[0] = LINTERP( t, out[0], in[0] );
+ dst[1] = LINTERP( t, out[1], in[1] );
+ dst[2] = LINTERP( t, out[2], in[2] );
+ dst[3] = LINTERP( t, out[3], in[3] );
}
+/**
+ * Copy front/back, primary/secondary colors from src vertex to dst vertex.
+ * Used when flat shading.
+ */
static void copy_colors( struct draw_stage *stage,
struct vertex_header *dst,
const struct vertex_header *src )
@@ -121,20 +124,17 @@ static void interp( const struct clip_stage *clip,
/* Vertex header.
*/
- {
- dst->clipmask = 0;
- dst->edgeflag = 0; /* will get overwritten later */
- dst->pad = 0;
- dst->vertex_id = UNDEFINED_VERTEX_ID;
- }
+ dst->clipmask = 0;
+ dst->edgeflag = 0; /* will get overwritten later */
+ dst->pad = 0;
+ dst->vertex_id = UNDEFINED_VERTEX_ID;
- /* Clip coordinates: interpolate normally
+ /* Interpolate the clip-space coords.
*/
- {
- interp_attr(dst->clip, t, in->clip, out->clip);
- }
+ interp_attr(dst->clip, t, in->clip, out->clip);
- /* Do the projective divide and insert window coordinates:
+ /* Do the projective divide and viewport transformation to get
+ * new window coordinates:
*/
{
const float *pos = dst->clip;
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 058aeedc17..397d4bf653 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -163,9 +163,11 @@ struct draw_context
/** vertex arrays */
const void *vbuffer[PIPE_MAX_ATTRIBS];
- /** constant buffer (for vertex/geometry shader) */
+ /** constant buffers (for vertex/geometry shader) */
const void *vs_constants[PIPE_MAX_CONSTANT_BUFFERS];
+ unsigned vs_constants_size[PIPE_MAX_CONSTANT_BUFFERS];
const void *gs_constants[PIPE_MAX_CONSTANT_BUFFERS];
+ unsigned gs_constants_size[PIPE_MAX_CONSTANT_BUFFERS];
} user;
boolean test_fse; /* enable FSE even though its not correct (eg for softpipe) */
@@ -198,6 +200,7 @@ struct draw_context
struct pipe_viewport_state viewport;
boolean identity_viewport;
+ /** Vertex shader state */
struct {
struct draw_vertex_shader *vertex_shader;
uint num_vs_outputs; /**< convenience, from vertex_shader */
@@ -227,6 +230,7 @@ struct draw_context
struct translate_cache *emit_cache;
} vs;
+ /** Geometry shader state */
struct {
struct draw_geometry_shader *geometry_shader;
uint num_gs_outputs; /**< convenience, from geometry_shader */
@@ -239,6 +243,7 @@ struct draw_context
struct tgsi_sampler **samplers;
} gs;
+ /** Stream output (vertex feedback) state */
struct {
struct pipe_stream_output_state state;
void *buffers[PIPE_MAX_SO_BUFFERS];
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 92d4113b4c..248927505d 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -259,6 +259,12 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
for (j = 0; j < draw->pt.nr_vertex_elements; j++) {
uint buf = draw->pt.vertex_element[j].vertex_buffer_index;
ubyte *ptr = (ubyte *) draw->pt.user.vbuffer[buf];
+
+ if (draw->pt.vertex_element[j].instance_divisor) {
+ ii = draw->instance_id / draw->pt.vertex_element[j].instance_divisor;
+ }
+
+ ptr += draw->pt.vertex_buffer[buf].buffer_offset;
ptr += draw->pt.vertex_buffer[buf].stride * ii;
ptr += draw->pt.vertex_element[j].src_offset;
@@ -341,19 +347,22 @@ draw_arrays_instanced(struct draw_context *draw,
unsigned reduced_prim = u_reduced_prim(mode);
unsigned instance;
+ assert(instanceCount > 0);
+
if (reduced_prim != draw->reduced_prim) {
draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);
draw->reduced_prim = reduced_prim;
}
if (0)
- draw_print_arrays(draw, mode, start, MIN2(count, 20));
-
- if (0) {
- unsigned int i;
debug_printf("draw_arrays(mode=%u start=%u count=%u):\n",
mode, start, count);
+
+ if (0)
tgsi_dump(draw->vs.vertex_shader->state.tokens, 0);
+
+ if (0) {
+ unsigned int i;
debug_printf("Elements:\n");
for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
debug_printf(" %u: src_offset=%u inst_div=%u vbuf=%u format=%s\n",
@@ -374,6 +383,9 @@ draw_arrays_instanced(struct draw_context *draw,
}
}
+ if (0)
+ draw_print_arrays(draw, mode, start, MIN2(count, 20));
+
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_decompose.h b/src/gallium/auxiliary/draw/draw_pt_decompose.h
index 52f9593d46..3127aad731 100644
--- a/src/gallium/auxiliary/draw/draw_pt_decompose.h
+++ b/src/gallium/auxiliary/draw/draw_pt_decompose.h
@@ -1,194 +1,7 @@
+#define LOCAL_VARS \
+ char *verts = (char *) vertices; \
+ const boolean last_vertex_last = \
+ !(draw->rasterizer->flatshade && \
+ draw->rasterizer->flatshade_first);
-
-static void FUNC( ARGS,
- unsigned count )
-{
- LOCAL_VARS;
-
- switch (prim) {
- case PIPE_PRIM_POINTS:
- for (i = 0; i < count; i ++) {
- POINT( (i + 0) );
- }
- break;
-
- case PIPE_PRIM_LINES:
- for (i = 0; i+1 < count; i += 2) {
- LINE( DRAW_PIPE_RESET_STIPPLE,
- (i + 0),
- (i + 1));
- }
- break;
-
- case PIPE_PRIM_LINE_LOOP:
- if (count >= 2) {
- flags = DRAW_PIPE_RESET_STIPPLE;
-
- for (i = 1; i < count; i++, flags = 0) {
- LINE( flags,
- (i - 1),
- (i ));
- }
-
- LINE( flags,
- (i - 1),
- (0 ));
- }
- break;
-
- case PIPE_PRIM_LINE_STRIP:
- flags = DRAW_PIPE_RESET_STIPPLE;
- for (i = 1; i < count; i++, flags = 0) {
- LINE( flags,
- (i - 1),
- (i ));
- }
- break;
-
- case PIPE_PRIM_TRIANGLES:
- for (i = 0; i+2 < count; i += 3) {
- TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- (i + 0),
- (i + 1),
- (i + 2 ));
- }
- break;
-
- case PIPE_PRIM_TRIANGLE_STRIP:
- if (flatfirst) {
- for (i = 0; i+2 < count; i++) {
- /* Emit first triangle vertex as first triangle vertex */
- TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- (i + 0),
- (i + 1 + (i&1)),
- (i + 2 - (i&1)) );
- }
- }
- else {
- for (i = 0; i+2 < count; i++) {
- /* Emit last triangle vertex as last triangle vertex */
- TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- (i + 0 + (i&1)),
- (i + 1 - (i&1)),
- (i + 2 ));
- }
- }
- break;
-
- case PIPE_PRIM_TRIANGLE_FAN:
- if (count >= 3) {
- if (flatfirst) {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- (i + 1),
- (i + 2),
- 0 );
- }
- }
- else {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- (0),
- (i + 1),
- (i + 2 ));
- }
- }
- }
- break;
-
-
- case PIPE_PRIM_QUADS:
- /* GL quads don't follow provoking vertex convention */
- if (flatfirst) {
- for (i = 0; i+3 < count; i += 4) {
- /* emit last quad vertex as first triangle vertex */
- QUAD_FIRST_PV( (i + 3),
- (i + 0),
- (i + 1),
- (i + 2) );
- }
- }
- else {
- for (i = 0; i+3 < count; i += 4) {
- /* emit last quad vertex as last triangle vertex */
- QUAD_LAST_PV( (i + 0),
- (i + 1),
- (i + 2),
- (i + 3) );
- }
- }
- break;
-
- case PIPE_PRIM_QUAD_STRIP:
- /* GL quad strips don't follow provoking vertex convention */
- if (flatfirst) {
- for (i = 0; i+3 < count; i += 2) {
- /* emit last quad vertex as first triangle vertex */
- QUAD_FIRST_PV( (i + 3),
- (i + 2),
- (i + 0),
- (i + 1) );
-
- }
- }
- else {
- for (i = 0; i+3 < count; i += 2) {
- /* emit last quad vertex as last triangle vertex */
- QUAD_LAST_PV( (i + 2),
- (i + 0),
- (i + 1),
- (i + 3) );
- }
- }
- break;
-
- case PIPE_PRIM_POLYGON:
- /* GL polygons don't follow provoking vertex convention */
- {
- /* These bitflags look a little odd because we submit the
- * vertices as (1,2,0) to satisfy flatshade requirements.
- */
- const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2;
- const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0;
- const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1;
-
- flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
-
- for (i = 0; i+2 < count; i++, flags = edge_middle) {
-
- if (i + 3 == count)
- flags |= edge_last;
-
- if (flatfirst) {
- /* emit first polygon vertex as first triangle vertex */
- TRIANGLE( flags,
- (0),
- (i + 1),
- (i + 2) );
- }
- else {
- /* emit first polygon vertex as last triangle vertex */
- TRIANGLE( flags,
- (i + 1),
- (i + 2),
- (0));
- }
- }
- }
- break;
-
- default:
- assert(0);
- break;
- }
-
- FLUSH;
-}
-
-
-#undef TRIANGLE
-#undef QUAD_FIRST_PV
-#undef QUAD_LAST_PV
-#undef POINT
-#undef LINE
-#undef FUNC
+#include "draw_decompose_tmp.h"
diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c
index 0229bcc7fe..5568fbb9f8 100644
--- a/src/gallium/auxiliary/draw/draw_pt_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_emit.c
@@ -182,6 +182,7 @@ void draw_pt_emit( struct pt_emit *emit,
0,
~0);
+ /* fetch/translate vertex attribs to fill hw_verts[] */
translate->run( translate,
0,
vertex_count,
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 121dfc414a..5b16c3788e 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -176,6 +176,7 @@ static void emit(struct pt_emit *emit,
static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
const struct draw_vertex_info *input_verts,
struct draw_vertex_info *output_verts )
{
@@ -190,6 +191,7 @@ static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
(const float (*)[4])input_verts->verts->data,
( float (*)[4])output_verts->verts->data,
constants,
+ const_size,
input_verts->count,
input_verts->vertex_size,
input_verts->vertex_size);
@@ -236,6 +238,7 @@ static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
if (fpme->opt & PT_SHADE) {
draw_vertex_shader_run(vshader,
draw->pt.user.vs_constants,
+ draw->pt.user.vs_constants_size,
vert_info,
&vs_vert_info);
@@ -246,6 +249,7 @@ static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
if ((fpme->opt & PT_SHADE) && gshader) {
draw_geometry_shader_run(gshader,
draw->pt.user.gs_constants,
+ draw->pt.user.gs_constants_size,
vert_info,
prim_info,
&gs_vert_info,
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
index bc074df8c2..4b99bee86a 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright 2010 VMWare, Inc.
+ * Copyright 2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -254,6 +254,7 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
if ((opt & PT_SHADE) && gshader) {
draw_geometry_shader_run(gshader,
draw->pt.user.gs_constants,
+ draw->pt.user.gs_constants_size,
vert_info,
prim_info,
&gs_vert_info,
diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
index 5d82934889..f7f4f24d35 100644
--- a/src/gallium/auxiliary/draw/draw_pt_so_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
@@ -218,25 +218,15 @@ static void so_tri(struct pt_so_emit *so, int i0, int i1, int i2)
}
-#define TRIANGLE(gs,i0,i1,i2) so_tri(so,i0,i1,i2)
-#define LINE(gs,i0,i1) so_line(so,i0,i1)
-#define POINT(gs,i0) so_point(so,i0)
-#define FUNC so_run_linear
-#define LOCAL_VARS
+#define FUNC so_run_linear
+#define GET_ELT(idx) (start + (idx))
#include "draw_so_emit_tmp.h"
-#undef LOCAL_VARS
-#undef FUNC
-#define TRIANGLE(gs,i0,i1,i2) so_tri(gs,elts[i0],elts[i1],elts[i2])
-#define LINE(gs,i0,i1) so_line(gs,elts[i0],elts[i1])
-#define POINT(gs,i0) so_point(gs,elts[i0])
-#define FUNC so_run_elts
-#define LOCAL_VARS \
- const ushort *elts = input_prims->elts;
+#define FUNC so_run_elts
+#define LOCAL_VARS const ushort *elts = input_prims->elts;
+#define GET_ELT(idx) (elts[start + (idx)] & ~DRAW_PIPE_FLAG_MASK)
#include "draw_so_emit_tmp.h"
-#undef LOCAL_VARS
-#undef FUNC
void draw_pt_so_emit( struct pt_so_emit *emit,
diff --git a/src/gallium/auxiliary/draw/draw_pt_util.c b/src/gallium/auxiliary/draw/draw_pt_util.c
index 3236d38e6a..182a597cca 100644
--- a/src/gallium/auxiliary/draw/draw_pt_util.c
+++ b/src/gallium/auxiliary/draw/draw_pt_util.c
@@ -53,7 +53,7 @@ void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr)
break;
case PIPE_PRIM_LINES_ADJACENCY:
*first = 4;
- *incr = 2;
+ *incr = 4;
break;
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
*first = 4;
@@ -65,7 +65,7 @@ void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr)
break;
case PIPE_PRIM_TRIANGLES_ADJACENCY:
*first = 6;
- *incr = 3;
+ *incr = 6;
break;
case PIPE_PRIM_TRIANGLE_STRIP:
case PIPE_PRIM_TRIANGLE_FAN:
@@ -75,7 +75,7 @@ void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr)
break;
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
*first = 6;
- *incr = 1;
+ *incr = 2;
break;
case PIPE_PRIM_QUADS:
*first = 4;
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
index a292346be9..55e43b2a71 100644
--- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
+++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
@@ -1,6 +1,11 @@
static unsigned trim( unsigned count, unsigned first, unsigned incr )
{
- return count - (count - first) % incr;
+ /*
+ * count either has been trimmed in draw_pt_arrays or is set to
+ * (driver)_fetch_max which is hopefully always larger than first.
+ */
+ assert(count >= first);
+ return count - (count - first) % incr;
}
static void FUNC(struct draw_pt_front_end *frontend,
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c
index 8ef94c3163..a848b54f7d 100644
--- a/src/gallium/auxiliary/draw/draw_pt_vcache.c
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c
@@ -95,7 +95,7 @@ static INLINE void
vcache_check_flush( struct vcache_frontend *vcache )
{
if (vcache->draw_count + 6 >= DRAW_MAX ||
- vcache->fetch_count + 4 >= FETCH_MAX) {
+ vcache->fetch_count + 6 >= FETCH_MAX) {
vcache_flush( vcache );
}
}
@@ -180,59 +180,61 @@ vcache_point( struct vcache_frontend *vcache,
}
-static INLINE void
-vcache_quad( struct vcache_frontend *vcache,
- unsigned i0,
- unsigned i1,
- unsigned i2,
- unsigned i3 )
+static INLINE void
+vcache_line_adj_flags( struct vcache_frontend *vcache,
+ unsigned flags,
+ unsigned a0, unsigned i0, unsigned i1, unsigned a1 )
{
- if (vcache->draw->rasterizer->flatshade_first) {
- /* pass last quad vertex as first triangle vertex */
- vcache_triangle( vcache, i3, i0, i1 );
- vcache_triangle( vcache, i3, i1, i2 );
- }
- else {
- /* pass last quad vertex as last triangle vertex */
- vcache_triangle( vcache, i0, i1, i3 );
- vcache_triangle( vcache, i1, i2, i3 );
- }
+ vcache_elt(vcache, a0, 0);
+ vcache_elt(vcache, i0, flags);
+ vcache_elt(vcache, i1, 0);
+ vcache_elt(vcache, a1, 0);
+ vcache_check_flush(vcache);
}
-static INLINE void
-vcache_ef_quad( struct vcache_frontend *vcache,
- unsigned i0,
- unsigned i1,
- unsigned i2,
- unsigned i3 )
+static INLINE void
+vcache_line_adj( struct vcache_frontend *vcache,
+ unsigned a0, unsigned i0, unsigned i1, unsigned a1 )
{
- if (vcache->draw->rasterizer->flatshade_first) {
- /* pass last quad vertex as first triangle vertex */
- vcache_triangle_flags( vcache,
- ( DRAW_PIPE_RESET_STIPPLE |
- DRAW_PIPE_EDGE_FLAG_0 |
- DRAW_PIPE_EDGE_FLAG_1 ),
- i3, i0, i1 );
-
- vcache_triangle_flags( vcache,
- ( DRAW_PIPE_EDGE_FLAG_1 |
- DRAW_PIPE_EDGE_FLAG_2 ),
- i3, i1, i2 );
- }
- else {
- /* pass last quad vertex as last triangle vertex */
- vcache_triangle_flags( vcache,
- ( DRAW_PIPE_RESET_STIPPLE |
- DRAW_PIPE_EDGE_FLAG_0 |
- DRAW_PIPE_EDGE_FLAG_2 ),
- i0, i1, i3 );
-
- vcache_triangle_flags( vcache,
- ( DRAW_PIPE_EDGE_FLAG_0 |
- DRAW_PIPE_EDGE_FLAG_1 ),
- i1, i2, i3 );
- }
+ vcache_elt(vcache, a0, 0);
+ vcache_elt(vcache, i0, 0);
+ vcache_elt(vcache, i1, 0);
+ vcache_elt(vcache, a1, 0);
+ vcache_check_flush(vcache);
+}
+
+
+static INLINE void
+vcache_triangle_adj_flags( struct vcache_frontend *vcache,
+ unsigned flags,
+ unsigned i0, unsigned a0,
+ unsigned i1, unsigned a1,
+ unsigned i2, unsigned a2 )
+{
+ vcache_elt(vcache, i0, flags);
+ vcache_elt(vcache, a0, 0);
+ vcache_elt(vcache, i1, 0);
+ vcache_elt(vcache, a1, 0);
+ vcache_elt(vcache, i2, 0);
+ vcache_elt(vcache, a2, 0);
+ vcache_check_flush(vcache);
+}
+
+
+static INLINE void
+vcache_triangle_adj( struct vcache_frontend *vcache,
+ unsigned i0, unsigned a0,
+ unsigned i1, unsigned a1,
+ unsigned i2, unsigned a2 )
+{
+ vcache_elt(vcache, i0, 0);
+ vcache_elt(vcache, a0, 0);
+ vcache_elt(vcache, i1, 0);
+ vcache_elt(vcache, a1, 0);
+ vcache_elt(vcache, i2, 0);
+ vcache_elt(vcache, a2, 0);
+ vcache_check_flush(vcache);
}
@@ -240,17 +242,23 @@ vcache_ef_quad( struct vcache_frontend *vcache,
* this. The two paths aren't too different though - it may be
* possible to reunify them.
*/
-#define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
-#define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3)
-#define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1)
-#define POINT(vc,i0) vcache_point(vc,i0)
+#define TRIANGLE(flags,i0,i1,i2) vcache_triangle_flags(vcache,flags,i0,i1,i2)
+#define LINE(flags,i0,i1) vcache_line_flags(vcache,flags,i0,i1)
+#define POINT(i0) vcache_point(vcache,i0)
+#define LINE_ADJ(flags,a0,i0,i1,a1) \
+ vcache_line_adj_flags(vcache,flags,a0,i0,i1,a1)
+#define TRIANGLE_ADJ(flags,i0,a0,i1,a1,i2,a2) \
+ vcache_triangle_adj_flags(vcache,flags,i0,a0,i1,a1,i2,a2)
#define FUNC vcache_run_extras
#include "draw_pt_vcache_tmp.h"
-#define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
-#define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3)
-#define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1)
-#define POINT(vc,i0) vcache_point(vc,i0)
+#define TRIANGLE(flags,i0,i1,i2) vcache_triangle(vcache,i0,i1,i2)
+#define LINE(flags,i0,i1) vcache_line(vcache,i0,i1)
+#define POINT(i0) vcache_point(vcache,i0)
+#define LINE_ADJ(flags,a0,i0,i1,a1) \
+ vcache_line_adj(vcache,a0,i0,i1,a1)
+#define TRIANGLE_ADJ(flags,i0,a0,i1,a1,i2,a2) \
+ vcache_triangle_adj(vcache,i0,a0,i1,a1,i2,a2)
#define FUNC vcache_run
#include "draw_pt_vcache_tmp.h"
@@ -339,6 +347,25 @@ format_from_get_elt( pt_elt_func get_elt )
#endif
+/**
+ * Check if any vertex attributes use instance divisors.
+ * Note that instance divisors complicate vertex fetching so we need
+ * to take the vcache path when they're in use.
+ */
+static boolean
+any_instance_divisors(const struct draw_context *draw)
+{
+ uint i;
+
+ for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
+ uint div = draw->pt.vertex_element[i].instance_divisor;
+ if (div)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
static INLINE void
vcache_check_run( struct draw_pt_front_end *frontend,
pt_elt_func get_elt,
@@ -382,6 +409,9 @@ vcache_check_run( struct draw_pt_front_end *frontend,
if (max_index >= (unsigned) DRAW_PIPE_MAX_VERTICES)
goto fail;
+ if (any_instance_divisors(draw))
+ goto fail;
+
fetch_count = max_index + 1 - min_index;
if (0)
@@ -518,7 +548,18 @@ vcache_prepare( struct draw_pt_front_end *frontend,
* which is a separate issue.
*/
vcache->input_prim = in_prim;
- vcache->output_prim = u_reduced_prim(in_prim);
+ switch (in_prim) {
+ case PIPE_PRIM_LINES_ADJACENCY:
+ case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+ vcache->output_prim = PIPE_PRIM_LINES_ADJACENCY;
+ break;
+ case PIPE_PRIM_TRIANGLES_ADJACENCY:
+ case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+ vcache->output_prim = PIPE_PRIM_TRIANGLES_ADJACENCY;
+ break;
+ default:
+ vcache->output_prim = u_reduced_prim(in_prim);
+ }
vcache->middle = middle;
vcache->opt = opt;
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h
index dac68ad439..1a3748d5f0 100644
--- a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h
@@ -1,198 +1,19 @@
+#define FUNC_VARS \
+ struct draw_pt_front_end *frontend, \
+ pt_elt_func get_elt, \
+ const void *elts, \
+ int elt_bias, \
+ unsigned count
+#define LOCAL_VARS \
+ struct vcache_frontend *vcache = (struct vcache_frontend *) frontend; \
+ struct draw_context *draw = vcache->draw; \
+ const unsigned prim = vcache->input_prim; \
+ const boolean last_vertex_last = !(draw->rasterizer->flatshade && \
+ draw->rasterizer->flatshade_first);
-static void FUNC( struct draw_pt_front_end *frontend,
- pt_elt_func get_elt,
- const void *elts,
- int elt_bias,
- unsigned count )
-{
- struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
- struct draw_context *draw = vcache->draw;
+#define GET_ELT(idx) (get_elt(elts, idx) + elt_bias)
- boolean flatfirst = (draw->rasterizer->flatshade &&
- draw->rasterizer->flatshade_first);
- unsigned i;
- ushort flags;
+#define FUNC_EXIT do { vcache_flush(vcache); } while (0)
- if (0) debug_printf("%s %d\n", __FUNCTION__, count);
-
-
- switch (vcache->input_prim) {
- case PIPE_PRIM_POINTS:
- for (i = 0; i < count; i ++) {
- POINT( vcache,
- get_elt(elts, i + 0) + elt_bias );
- }
- break;
-
- case PIPE_PRIM_LINES:
- for (i = 0; i+1 < count; i += 2) {
- LINE( vcache,
- DRAW_PIPE_RESET_STIPPLE,
- get_elt(elts, i + 0) + elt_bias,
- get_elt(elts, i + 1) + elt_bias);
- }
- break;
-
- case PIPE_PRIM_LINE_LOOP:
- if (count >= 2) {
- flags = DRAW_PIPE_RESET_STIPPLE;
-
- for (i = 1; i < count; i++, flags = 0) {
- LINE( vcache,
- flags,
- get_elt(elts, i - 1) + elt_bias,
- get_elt(elts, i ) + elt_bias);
- }
-
- LINE( vcache,
- flags,
- get_elt(elts, i - 1) + elt_bias,
- get_elt(elts, 0 ) + elt_bias);
- }
- break;
-
- case PIPE_PRIM_LINE_STRIP:
- flags = DRAW_PIPE_RESET_STIPPLE;
- for (i = 1; i < count; i++, flags = 0) {
- LINE( vcache,
- flags,
- get_elt(elts, i - 1) + elt_bias,
- get_elt(elts, i ) + elt_bias);
- }
- break;
-
- case PIPE_PRIM_TRIANGLES:
- for (i = 0; i+2 < count; i += 3) {
- TRIANGLE( vcache,
- DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- get_elt(elts, i + 0) + elt_bias,
- get_elt(elts, i + 1) + elt_bias,
- get_elt(elts, i + 2 ) + elt_bias);
- }
- break;
-
- case PIPE_PRIM_TRIANGLE_STRIP:
- if (flatfirst) {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( vcache,
- DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- get_elt(elts, i + 0) + elt_bias,
- get_elt(elts, i + 1 + (i&1)) + elt_bias,
- get_elt(elts, i + 2 - (i&1)) + elt_bias);
- }
- }
- else {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( vcache,
- DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- get_elt(elts, i + 0 + (i&1)) + elt_bias,
- get_elt(elts, i + 1 - (i&1)) + elt_bias,
- get_elt(elts, i + 2 ) + elt_bias);
- }
- }
- break;
-
- case PIPE_PRIM_TRIANGLE_FAN:
- if (count >= 3) {
- if (flatfirst) {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( vcache,
- DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- get_elt(elts, i + 1) + elt_bias,
- get_elt(elts, i + 2) + elt_bias,
- get_elt(elts, 0 ) + elt_bias);
- }
- }
- else {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( vcache,
- DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- get_elt(elts, 0) + elt_bias,
- get_elt(elts, i + 1) + elt_bias,
- get_elt(elts, i + 2 ) + elt_bias);
- }
- }
- }
- break;
-
-
- case PIPE_PRIM_QUADS:
- for (i = 0; i+3 < count; i += 4) {
- QUAD( vcache,
- get_elt(elts, i + 0) + elt_bias,
- get_elt(elts, i + 1) + elt_bias,
- get_elt(elts, i + 2) + elt_bias,
- get_elt(elts, i + 3) + elt_bias );
- }
- break;
-
- case PIPE_PRIM_QUAD_STRIP:
- for (i = 0; i+3 < count; i += 2) {
- QUAD( vcache,
- get_elt(elts, i + 2) + elt_bias,
- get_elt(elts, i + 0) + elt_bias,
- get_elt(elts, i + 1) + elt_bias,
- get_elt(elts, i + 3) + elt_bias );
- }
- break;
-
- case PIPE_PRIM_POLYGON:
- {
- /* These bitflags look a little odd because we submit the
- * vertices as (1,2,0) to satisfy flatshade requirements.
- */
- ushort edge_next, edge_finish;
-
- if (flatfirst) {
- flags = (DRAW_PIPE_RESET_STIPPLE |
- DRAW_PIPE_EDGE_FLAG_1 |
- DRAW_PIPE_EDGE_FLAG_2);
- edge_next = DRAW_PIPE_EDGE_FLAG_2;
- edge_finish = DRAW_PIPE_EDGE_FLAG_0;
- }
- else {
- flags = (DRAW_PIPE_RESET_STIPPLE |
- DRAW_PIPE_EDGE_FLAG_2 |
- DRAW_PIPE_EDGE_FLAG_0);
- edge_next = DRAW_PIPE_EDGE_FLAG_0;
- edge_finish = DRAW_PIPE_EDGE_FLAG_1;
- }
-
- for (i = 0; i+2 < count; i++, flags = edge_next) {
-
- if (i + 3 == count)
- flags |= edge_finish;
-
- if (flatfirst) {
- TRIANGLE( vcache,
- flags,
- get_elt(elts, 0) + elt_bias,
- get_elt(elts, i + 1) + elt_bias,
- get_elt(elts, i + 2) + elt_bias );
- }
- else {
- TRIANGLE( vcache,
- flags,
- get_elt(elts, i + 1) + elt_bias,
- get_elt(elts, i + 2) + elt_bias,
- get_elt(elts, 0) + elt_bias);
- }
- }
- }
- break;
-
- default:
- assert(0);
- break;
- }
-
- vcache_flush( vcache );
-}
-
-
-#undef TRIANGLE
-#undef QUAD
-#undef POINT
-#undef LINE
-#undef FUNC
+#include "draw_decompose_tmp.h"
diff --git a/src/gallium/auxiliary/draw/draw_so_emit_tmp.h b/src/gallium/auxiliary/draw/draw_so_emit_tmp.h
index 01212a8e53..6d8937a0b4 100644
--- a/src/gallium/auxiliary/draw/draw_so_emit_tmp.h
+++ b/src/gallium/auxiliary/draw/draw_so_emit_tmp.h
@@ -1,123 +1,33 @@
-
-static void FUNC( struct pt_so_emit *so,
- const struct draw_prim_info *input_prims,
- const struct draw_vertex_info *input_verts,
- unsigned start,
- unsigned count)
-{
- struct draw_context *draw = so->draw;
-
- boolean flatfirst = (draw->rasterizer->flatshade &&
- draw->rasterizer->flatshade_first);
- unsigned i;
- LOCAL_VARS
-
- if (0) debug_printf("%s %d\n", __FUNCTION__, count);
-
- debug_assert(input_prims->primitive_count == 1);
-
- switch (input_prims->prim) {
- case PIPE_PRIM_POINTS:
- for (i = 0; i < count; i++) {
- POINT( so, start + i + 0 );
- }
- break;
-
- case PIPE_PRIM_LINES:
- for (i = 0; i+1 < count; i += 2) {
- LINE( so , start + i + 0 , start + i + 1 );
- }
- break;
-
- case PIPE_PRIM_LINE_LOOP:
- if (count >= 2) {
-
- for (i = 1; i < count; i++) {
- LINE( so, start + i - 1, start + i );
- }
-
- LINE( so, start + i - 1, start );
- }
- break;
-
- case PIPE_PRIM_LINE_STRIP:
- for (i = 1; i < count; i++) {
- LINE( so, start + i - 1, start + i );
- }
- break;
-
- case PIPE_PRIM_TRIANGLES:
- for (i = 0; i+2 < count; i += 3) {
- TRIANGLE( so, start + i + 0, start + i + 1, start + i + 2 );
- }
- break;
-
- case PIPE_PRIM_TRIANGLE_STRIP:
- if (flatfirst) {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( so,
- start + i + 0,
- start + i + 1 + (i&1),
- start + i + 2 - (i&1) );
- }
- }
- else {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( so,
- start + i + 0 + (i&1),
- start + i + 1 - (i&1),
- start + i + 2 );
- }
- }
- break;
-
- case PIPE_PRIM_TRIANGLE_FAN:
- if (count >= 3) {
- if (flatfirst) {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( so,
- start + i + 1,
- start + i + 2,
- start );
- }
- }
- else {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE( so,
- start,
- start + i + 1,
- start + i + 2 );
- }
- }
- }
- break;
-
- case PIPE_PRIM_POLYGON:
- {
- /* These bitflags look a little odd because we submit the
- * vertices as (1,2,0) to satisfy flatshade requirements.
- */
-
- for (i = 0; i+2 < count; i++) {
-
- if (flatfirst) {
- TRIANGLE( so, start + 0, start + i + 1, start + i + 2 );
- }
- else {
- TRIANGLE( so, start + i + 1, start + i + 2, start + 0 );
- }
- }
- }
- break;
-
- default:
- debug_assert(!"Unsupported primitive in stream output");
- break;
- }
-}
-
-
-#undef TRIANGLE
-#undef POINT
-#undef LINE
-#undef FUNC
+#define FUNC_VARS \
+ struct pt_so_emit *so, \
+ const struct draw_prim_info *input_prims, \
+ const struct draw_vertex_info *input_verts, \
+ unsigned start, \
+ unsigned count
+
+#define FUNC_ENTER \
+ /* declare more local vars */ \
+ struct draw_context *draw = so->draw; \
+ const unsigned prim = input_prims->prim; \
+ const boolean last_vertex_last = \
+ !(draw->rasterizer->flatshade && \
+ draw->rasterizer->flatshade_first); \
+ do { \
+ debug_assert(input_prims->primitive_count == 1); \
+ switch (prim) { \
+ case PIPE_PRIM_LINES_ADJACENCY: \
+ case PIPE_PRIM_LINE_STRIP_ADJACENCY: \
+ case PIPE_PRIM_TRIANGLES_ADJACENCY: \
+ case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: \
+ debug_assert(!"unexpected primitive type in stream output"); \
+ return; \
+ default: \
+ break; \
+ } \
+ } while (0) \
+
+#define POINT(i0) so_point(so,i0)
+#define LINE(flags,i0,i1) so_line(so,i0,i1)
+#define TRIANGLE(flags,i0,i1,i2) so_tri(so,i0,i1,i2)
+
+#include "draw_decompose_tmp.h"
diff --git a/src/gallium/auxiliary/draw/draw_vertex.h b/src/gallium/auxiliary/draw/draw_vertex.h
index 3af31ffe12..e63cf5f4f9 100644
--- a/src/gallium/auxiliary/draw/draw_vertex.h
+++ b/src/gallium/auxiliary/draw/draw_vertex.h
@@ -166,7 +166,7 @@ static INLINE enum pipe_format draw_translate_vinfo_format(enum attrib_emit emit
}
}
-static INLINE enum attrib_emit draw_translate_vinfo_size(enum attrib_emit emit)
+static INLINE unsigned draw_translate_vinfo_size(enum attrib_emit emit)
{
switch (emit) {
case EMIT_OMIT:
diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c
index 57ea63fc06..fb665b08ff 100644
--- a/src/gallium/auxiliary/draw/draw_vs.c
+++ b/src/gallium/auxiliary/draw/draw_vs.c
@@ -48,18 +48,30 @@
DEBUG_GET_ONCE_BOOL_OPTION(gallium_dump_vs, "GALLIUM_DUMP_VS", FALSE)
+
+/**
+ * Set a vertex shader constant buffer.
+ * \param slot which constant buffer in [0, PIPE_MAX_CONSTANT_BUFFERS-1]
+ * \param constants the mapped buffer
+ * \param size size of buffer in bytes
+ */
void
draw_vs_set_constants(struct draw_context *draw,
unsigned slot,
const void *constants,
unsigned size)
{
- if (((uintptr_t)constants) & 0xf) {
+ const int alignment = 16;
+
+ /* check if buffer is 16-byte aligned */
+ if (((uintptr_t)constants) & (alignment - 1)) {
+ /* if not, copy the constants into a new, 16-byte aligned buffer */
if (size > draw->vs.const_storage_size[slot]) {
if (draw->vs.aligned_constant_storage[slot]) {
align_free((void *)draw->vs.aligned_constant_storage[slot]);
}
- draw->vs.aligned_constant_storage[slot] = align_malloc(size, 16);
+ draw->vs.aligned_constant_storage[slot] =
+ align_malloc(size, alignment);
}
assert(constants);
memcpy((void *)draw->vs.aligned_constant_storage[slot],
diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h
index a731994523..f9a038788f 100644
--- a/src/gallium/auxiliary/draw/draw_vs.h
+++ b/src/gallium/auxiliary/draw/draw_vs.h
@@ -133,7 +133,8 @@ struct draw_vertex_shader {
void (*run_linear)( struct draw_vertex_shader *shader,
const float (*input)[4],
float (*output)[4],
- const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
unsigned count,
unsigned input_stride,
unsigned output_stride );
diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c
index bc34d390da..dab3eb1ca8 100644
--- a/src/gallium/auxiliary/draw/draw_vs_exec.c
+++ b/src/gallium/auxiliary/draw/draw_vs_exec.c
@@ -85,7 +85,8 @@ static void
vs_exec_run_linear( struct draw_vertex_shader *shader,
const float (*input)[4],
float (*output)[4],
- const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
unsigned count,
unsigned input_stride,
unsigned output_stride )
@@ -95,9 +96,8 @@ vs_exec_run_linear( struct draw_vertex_shader *shader,
unsigned int i, j;
unsigned slot;
- for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
- machine->Consts[i] = constants[i];
- }
+ tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
+ constants, const_size);
for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c
index 6c13df7913..d13ad24fff 100644
--- a/src/gallium/auxiliary/draw/draw_vs_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c
@@ -49,6 +49,7 @@ vs_llvm_run_linear( struct draw_vertex_shader *shader,
const float (*input)[4],
float (*output)[4],
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
unsigned count,
unsigned input_stride,
unsigned output_stride )
diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c
index 14c95082a9..0b0c6077c6 100644
--- a/src/gallium/auxiliary/draw/draw_vs_sse.c
+++ b/src/gallium/auxiliary/draw/draw_vs_sse.c
@@ -84,6 +84,7 @@ vs_sse_run_linear( struct draw_vertex_shader *base,
const float (*input)[4],
float (*output)[4],
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+ const unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
unsigned count,
unsigned input_stride,
unsigned output_stride )
diff --git a/src/gallium/auxiliary/draw/draw_vs_varient.c b/src/gallium/auxiliary/draw/draw_vs_varient.c
index 6eb26927f2..eacd160187 100644
--- a/src/gallium/auxiliary/draw/draw_vs_varient.c
+++ b/src/gallium/auxiliary/draw/draw_vs_varient.c
@@ -149,7 +149,8 @@ static void PIPE_CDECL vsvg_run_elts( struct draw_vs_varient *varient,
vsvg->base.vs->run_linear( vsvg->base.vs,
temp_buffer,
temp_buffer,
- vsvg->base.vs->draw->pt.user.vs_constants,
+ vsvg->base.vs->draw->pt.user.vs_constants,
+ vsvg->base.vs->draw->pt.user.vs_constants_size,
count,
temp_vertex_stride,
temp_vertex_stride);
@@ -214,7 +215,8 @@ static void PIPE_CDECL vsvg_run_linear( struct draw_vs_varient *varient,
vsvg->base.vs->run_linear( vsvg->base.vs,
temp_buffer,
temp_buffer,
- vsvg->base.vs->draw->pt.user.vs_constants,
+ vsvg->base.vs->draw->pt.user.vs_constants,
+ vsvg->base.vs->draw->pt.user.vs_constants_size,
count,
temp_vertex_stride,
temp_vertex_stride);
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
index f5f2623e46..7b35dd4bb4 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright 2009 VMware, Inc.
+ * Copyright 2009-2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -59,6 +59,19 @@
#include "lp_bld_arit.h"
+/*
+ * XXX: Increasing eliminates some artifacts, but adds others, most
+ * noticeably corruption in the Earth halo in Google Earth.
+ */
+#define RCP_NEWTON_STEPS 0
+
+#define RSQRT_NEWTON_STEPS 0
+
+#define EXP_POLY_DEGREE 3
+
+#define LOG_POLY_DEGREE 5
+
+
/**
* Generate min(a, b)
* No checks for special case values of a or b = 1 or 0 are done.
@@ -72,6 +85,9 @@ lp_build_min_simple(struct lp_build_context *bld,
const char *intrinsic = NULL;
LLVMValueRef cond;
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
+
/* TODO: optimize the constant case */
if(type.width * type.length == 128) {
@@ -118,6 +134,9 @@ lp_build_max_simple(struct lp_build_context *bld,
const char *intrinsic = NULL;
LLVMValueRef cond;
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
+
/* TODO: optimize the constant case */
if(type.width * type.length == 128) {
@@ -160,6 +179,8 @@ lp_build_comp(struct lp_build_context *bld,
{
const struct lp_type type = bld->type;
+ assert(lp_check_value(type, a));
+
if(a == bld->one)
return bld->zero;
if(a == bld->zero)
@@ -173,9 +194,15 @@ lp_build_comp(struct lp_build_context *bld,
}
if(LLVMIsConstant(a))
- return LLVMConstSub(bld->one, a);
+ if (type.floating)
+ return LLVMConstFSub(bld->one, a);
+ else
+ return LLVMConstSub(bld->one, a);
else
- return LLVMBuildSub(bld->builder, bld->one, a, "");
+ if (type.floating)
+ return LLVMBuildFSub(bld->builder, bld->one, a, "");
+ else
+ return LLVMBuildSub(bld->builder, bld->one, a, "");
}
@@ -190,6 +217,9 @@ lp_build_add(struct lp_build_context *bld,
const struct lp_type type = bld->type;
LLVMValueRef res;
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
+
if(a == bld->zero)
return b;
if(b == bld->zero)
@@ -217,9 +247,15 @@ lp_build_add(struct lp_build_context *bld,
}
if(LLVMIsConstant(a) && LLVMIsConstant(b))
- res = LLVMConstAdd(a, b);
+ if (type.floating)
+ res = LLVMConstFAdd(a, b);
+ else
+ res = LLVMConstAdd(a, b);
else
- res = LLVMBuildAdd(bld->builder, a, b, "");
+ if (type.floating)
+ res = LLVMBuildFAdd(bld->builder, a, b, "");
+ else
+ res = LLVMBuildAdd(bld->builder, a, b, "");
/* clamp to ceiling of 1.0 */
if(bld->type.norm && (bld->type.floating || bld->type.fixed))
@@ -240,6 +276,8 @@ lp_build_sum_vector(struct lp_build_context *bld,
LLVMValueRef index, res;
unsigned i;
+ assert(lp_check_value(type, a));
+
if (a == bld->zero)
return bld->zero;
if (a == bld->undef)
@@ -253,9 +291,16 @@ lp_build_sum_vector(struct lp_build_context *bld,
for (i = 1; i < type.length; i++) {
index = LLVMConstInt(LLVMInt32Type(), i, 0);
- res = LLVMBuildAdd(bld->builder, res,
- LLVMBuildExtractElement(bld->builder, a, index, ""),
- "");
+ if (type.floating)
+ res = LLVMBuildFAdd(bld->builder, res,
+ LLVMBuildExtractElement(bld->builder,
+ a, index, ""),
+ "");
+ else
+ res = LLVMBuildAdd(bld->builder, res,
+ LLVMBuildExtractElement(bld->builder,
+ a, index, ""),
+ "");
}
return res;
@@ -273,6 +318,9 @@ lp_build_sub(struct lp_build_context *bld,
const struct lp_type type = bld->type;
LLVMValueRef res;
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
+
if(b == bld->zero)
return a;
if(a == bld->undef || b == bld->undef)
@@ -300,9 +348,15 @@ lp_build_sub(struct lp_build_context *bld,
}
if(LLVMIsConstant(a) && LLVMIsConstant(b))
- res = LLVMConstSub(a, b);
+ if (type.floating)
+ res = LLVMConstFSub(a, b);
+ else
+ res = LLVMConstSub(a, b);
else
- res = LLVMBuildSub(bld->builder, a, b, "");
+ if (type.floating)
+ res = LLVMBuildFSub(bld->builder, a, b, "");
+ else
+ res = LLVMBuildSub(bld->builder, a, b, "");
if(bld->type.norm && (bld->type.floating || bld->type.fixed))
res = lp_build_max_simple(bld, res, bld->zero);
@@ -360,6 +414,10 @@ lp_build_mul_u8n(LLVMBuilderRef builder,
LLVMValueRef c8;
LLVMValueRef ab;
+ assert(!i16_type.floating);
+ assert(lp_check_value(i16_type, a));
+ assert(lp_check_value(i16_type, b));
+
c8 = lp_build_const_int_vec(i16_type, 8);
#if 0
@@ -395,6 +453,9 @@ lp_build_mul(struct lp_build_context *bld,
LLVMValueRef shift;
LLVMValueRef res;
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
+
if(a == bld->zero)
return bld->zero;
if(a == bld->one)
@@ -433,7 +494,10 @@ lp_build_mul(struct lp_build_context *bld,
shift = NULL;
if(LLVMIsConstant(a) && LLVMIsConstant(b)) {
- res = LLVMConstMul(a, b);
+ if (type.floating)
+ res = LLVMConstFMul(a, b);
+ else
+ res = LLVMConstMul(a, b);
if(shift) {
if(type.sign)
res = LLVMConstAShr(res, shift);
@@ -442,7 +506,10 @@ lp_build_mul(struct lp_build_context *bld,
}
}
else {
- res = LLVMBuildMul(bld->builder, a, b, "");
+ if (type.floating)
+ res = LLVMBuildFMul(bld->builder, a, b, "");
+ else
+ res = LLVMBuildMul(bld->builder, a, b, "");
if(shift) {
if(type.sign)
res = LLVMBuildAShr(bld->builder, res, shift, "");
@@ -465,6 +532,8 @@ lp_build_mul_imm(struct lp_build_context *bld,
{
LLVMValueRef factor;
+ assert(lp_check_value(bld->type, a));
+
if(b == 0)
return bld->zero;
@@ -472,7 +541,7 @@ lp_build_mul_imm(struct lp_build_context *bld,
return a;
if(b == -1)
- return LLVMBuildNeg(bld->builder, a, "");
+ return lp_build_negate(bld, a);
if(b == 2 && bld->type.floating)
return lp_build_add(bld, a, a);
@@ -518,6 +587,9 @@ lp_build_div(struct lp_build_context *bld,
{
const struct lp_type type = bld->type;
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
+
if(a == bld->zero)
return bld->zero;
if(a == bld->one)
@@ -529,13 +601,24 @@ lp_build_div(struct lp_build_context *bld,
if(a == bld->undef || b == bld->undef)
return bld->undef;
- if(LLVMIsConstant(a) && LLVMIsConstant(b))
- return LLVMConstFDiv(a, b);
+ if(LLVMIsConstant(a) && LLVMIsConstant(b)) {
+ if (type.floating)
+ return LLVMConstFDiv(a, b);
+ else if (type.sign)
+ return LLVMConstSDiv(a, b);
+ else
+ return LLVMConstUDiv(a, b);
+ }
if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4)
return lp_build_mul(bld, a, lp_build_rcp(bld, b));
- return LLVMBuildFDiv(bld->builder, a, b, "");
+ if (type.floating)
+ return LLVMBuildFDiv(bld->builder, a, b, "");
+ else if (type.sign)
+ return LLVMBuildSDiv(bld->builder, a, b, "");
+ else
+ return LLVMBuildUDiv(bld->builder, a, b, "");
}
@@ -555,6 +638,10 @@ lp_build_lerp(struct lp_build_context *bld,
LLVMValueRef delta;
LLVMValueRef res;
+ assert(lp_check_value(bld->type, x));
+ assert(lp_check_value(bld->type, v0));
+ assert(lp_check_value(bld->type, v1));
+
delta = lp_build_sub(bld, v1, v0);
res = lp_build_mul(bld, x, delta);
@@ -596,6 +683,9 @@ lp_build_min(struct lp_build_context *bld,
LLVMValueRef a,
LLVMValueRef b)
{
+ assert(lp_check_value(bld->type, a));
+ assert(lp_check_value(bld->type, b));
+
if(a == bld->undef || b == bld->undef)
return bld->undef;
@@ -624,6 +714,9 @@ lp_build_max(struct lp_build_context *bld,
LLVMValueRef a,
LLVMValueRef b)
{
+ assert(lp_check_value(bld->type, a));
+ assert(lp_check_value(bld->type, b));
+
if(a == bld->undef || b == bld->undef)
return bld->undef;
@@ -653,6 +746,10 @@ lp_build_clamp(struct lp_build_context *bld,
LLVMValueRef min,
LLVMValueRef max)
{
+ assert(lp_check_value(bld->type, a));
+ assert(lp_check_value(bld->type, min));
+ assert(lp_check_value(bld->type, max));
+
a = lp_build_min(bld, a, max);
a = lp_build_max(bld, a, min);
return a;
@@ -669,6 +766,8 @@ lp_build_abs(struct lp_build_context *bld,
const struct lp_type type = bld->type;
LLVMTypeRef vec_type = lp_build_vec_type(type);
+ assert(lp_check_value(type, a));
+
if(!type.sign)
return a;
@@ -702,7 +801,16 @@ LLVMValueRef
lp_build_negate(struct lp_build_context *bld,
LLVMValueRef a)
{
- return LLVMBuildNeg(bld->builder, a, "");
+ assert(lp_check_value(bld->type, a));
+
+#if HAVE_LLVM >= 0x0207
+ if (bld->type.floating)
+ a = LLVMBuildFNeg(bld->builder, a, "");
+ else
+#endif
+ a = LLVMBuildNeg(bld->builder, a, "");
+
+ return a;
}
@@ -715,6 +823,8 @@ lp_build_sgn(struct lp_build_context *bld,
LLVMValueRef cond;
LLVMValueRef res;
+ assert(lp_check_value(type, a));
+
/* Handle non-zero case */
if(!type.sign) {
/* if not zero then sign must be positive */
@@ -773,6 +883,7 @@ lp_build_set_sign(struct lp_build_context *bld,
LLVMValueRef val, res;
assert(type.floating);
+ assert(lp_check_value(type, a));
/* val = reinterpret_cast<int>(a) */
val = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
@@ -1021,7 +1132,7 @@ lp_build_iround(struct lp_build_context *bld,
half = LLVMBuildOr(bld->builder, sign, half, "");
half = LLVMBuildBitCast(bld->builder, half, vec_type, "");
- res = LLVMBuildAdd(bld->builder, a, half, "");
+ res = LLVMBuildFAdd(bld->builder, a, half, "");
}
res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, "");
@@ -1070,7 +1181,7 @@ lp_build_ifloor(struct lp_build_context *bld,
offset = LLVMBuildAnd(bld->builder, offset, sign, "");
offset = LLVMBuildBitCast(bld->builder, offset, vec_type, "ifloor.offset");
- res = LLVMBuildAdd(bld->builder, a, offset, "ifloor.res");
+ res = LLVMBuildFAdd(bld->builder, a, offset, "ifloor.res");
}
/* round to nearest (toward zero) */
@@ -1120,7 +1231,7 @@ lp_build_iceil(struct lp_build_context *bld,
offset = LLVMBuildAnd(bld->builder, offset, sign, "");
offset = LLVMBuildBitCast(bld->builder, offset, vec_type, "iceil.offset");
- res = LLVMBuildAdd(bld->builder, a, offset, "iceil.res");
+ res = LLVMBuildFAdd(bld->builder, a, offset, "iceil.res");
}
/* round to nearest (toward zero) */
@@ -1138,6 +1249,8 @@ lp_build_sqrt(struct lp_build_context *bld,
LLVMTypeRef vec_type = lp_build_vec_type(type);
char intrinsic[32];
+ assert(lp_check_value(type, a));
+
/* TODO: optimize the constant case */
/* TODO: optimize the constant case */
@@ -1148,12 +1261,39 @@ lp_build_sqrt(struct lp_build_context *bld,
}
+/**
+ * Do one Newton-Raphson step to improve reciprocate precision:
+ *
+ * x_{i+1} = x_i * (2 - a * x_i)
+ *
+ * See also:
+ * - http://en.wikipedia.org/wiki/Division_(digital)#Newton.E2.80.93Raphson_division
+ * - http://softwarecommunity.intel.com/articles/eng/1818.htm
+ */
+static INLINE LLVMValueRef
+lp_build_rcp_refine(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef rcp_a)
+{
+ LLVMValueRef two = lp_build_const_vec(bld->type, 2.0);
+ LLVMValueRef res;
+
+ res = LLVMBuildFMul(bld->builder, a, rcp_a, "");
+ res = LLVMBuildFSub(bld->builder, two, res, "");
+ res = LLVMBuildFMul(bld->builder, rcp_a, res, "");
+
+ return res;
+}
+
+
LLVMValueRef
lp_build_rcp(struct lp_build_context *bld,
LLVMValueRef a)
{
const struct lp_type type = bld->type;
+ assert(lp_check_value(type, a));
+
if(a == bld->zero)
return bld->undef;
if(a == bld->one)
@@ -1167,32 +1307,16 @@ lp_build_rcp(struct lp_build_context *bld,
return LLVMConstFDiv(bld->one, a);
if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
- /*
- * XXX: Added precision is not always necessary, so only enable this
- * when we have a better system in place to track minimum precision.
- */
-
-#if 0
- /*
- * Do one Newton-Raphson step to improve precision:
- *
- * x1 = (2 - a * rcp(a)) * rcp(a)
- */
-
- LLVMValueRef two = lp_build_const_vec(bld->type, 2.0);
- LLVMValueRef rcp_a;
LLVMValueRef res;
+ unsigned i;
- rcp_a = lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rcp.ps", lp_build_vec_type(type), a);
+ res = lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rcp.ps", bld->vec_type, a);
- res = LLVMBuildMul(bld->builder, a, rcp_a, "");
- res = LLVMBuildSub(bld->builder, two, res, "");
- res = LLVMBuildMul(bld->builder, res, rcp_a, "");
+ for (i = 0; i < RCP_NEWTON_STEPS; ++i) {
+ res = lp_build_rcp_refine(bld, a, res);
+ }
- return rcp_a;
-#else
- return lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rcp.ps", lp_build_vec_type(type), a);
-#endif
+ return res;
}
return LLVMBuildFDiv(bld->builder, bld->one, a, "");
@@ -1200,6 +1324,33 @@ lp_build_rcp(struct lp_build_context *bld,
/**
+ * Do one Newton-Raphson step to improve rsqrt precision:
+ *
+ * x_{i+1} = 0.5 * x_i * (3.0 - a * x_i * x_i)
+ *
+ * See also:
+ * - http://softwarecommunity.intel.com/articles/eng/1818.htm
+ */
+static INLINE LLVMValueRef
+lp_build_rsqrt_refine(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef rsqrt_a)
+{
+ LLVMValueRef half = lp_build_const_vec(bld->type, 0.5);
+ LLVMValueRef three = lp_build_const_vec(bld->type, 3.0);
+ LLVMValueRef res;
+
+ res = LLVMBuildFMul(bld->builder, rsqrt_a, rsqrt_a, "");
+ res = LLVMBuildFMul(bld->builder, a, res, "");
+ res = LLVMBuildFSub(bld->builder, three, res, "");
+ res = LLVMBuildFMul(bld->builder, rsqrt_a, res, "");
+ res = LLVMBuildFMul(bld->builder, half, res, "");
+
+ return res;
+}
+
+
+/**
* Generate 1/sqrt(a)
*/
LLVMValueRef
@@ -1208,10 +1359,22 @@ lp_build_rsqrt(struct lp_build_context *bld,
{
const struct lp_type type = bld->type;
+ assert(lp_check_value(type, a));
+
assert(type.floating);
- if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4)
- return lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rsqrt.ps", lp_build_vec_type(type), a);
+ if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
+ LLVMValueRef res;
+ unsigned i;
+
+ res = lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rsqrt.ps", bld->vec_type, a);
+
+ for (i = 0; i < RSQRT_NEWTON_STEPS; ++i) {
+ res = lp_build_rsqrt_refine(bld, a, res);
+ }
+
+ return res;
+ }
return lp_build_rcp(bld, lp_build_sqrt(bld, a));
}
@@ -1270,7 +1433,7 @@ lp_build_sin(struct lp_build_context *bld,
*/
LLVMValueRef FOPi = lp_build_const_v4sf(1.27323954473516);
- LLVMValueRef scale_y = LLVMBuildMul(b, x_abs, FOPi, "scale_y");
+ LLVMValueRef scale_y = LLVMBuildFMul(b, x_abs, FOPi, "scale_y");
/*
* store the integer part of y in mm0
@@ -1344,9 +1507,9 @@ lp_build_sin(struct lp_build_context *bld,
* xmm2 = _mm_mul_ps(y, xmm2);
* xmm3 = _mm_mul_ps(y, xmm3);
*/
- LLVMValueRef xmm1 = LLVMBuildMul(b, y_2, DP1, "xmm1");
- LLVMValueRef xmm2 = LLVMBuildMul(b, y_2, DP2, "xmm2");
- LLVMValueRef xmm3 = LLVMBuildMul(b, y_2, DP3, "xmm3");
+ LLVMValueRef xmm1 = LLVMBuildFMul(b, y_2, DP1, "xmm1");
+ LLVMValueRef xmm2 = LLVMBuildFMul(b, y_2, DP2, "xmm2");
+ LLVMValueRef xmm3 = LLVMBuildFMul(b, y_2, DP3, "xmm3");
/*
* x = _mm_add_ps(x, xmm1);
@@ -1354,16 +1517,16 @@ lp_build_sin(struct lp_build_context *bld,
* x = _mm_add_ps(x, xmm3);
*/
- LLVMValueRef x_1 = LLVMBuildAdd(b, x_abs, xmm1, "x_1");
- LLVMValueRef x_2 = LLVMBuildAdd(b, x_1, xmm2, "x_2");
- LLVMValueRef x_3 = LLVMBuildAdd(b, x_2, xmm3, "x_3");
+ LLVMValueRef x_1 = LLVMBuildFAdd(b, x_abs, xmm1, "x_1");
+ LLVMValueRef x_2 = LLVMBuildFAdd(b, x_1, xmm2, "x_2");
+ LLVMValueRef x_3 = LLVMBuildFAdd(b, x_2, xmm3, "x_3");
/*
* Evaluate the first polynom (0 <= x <= Pi/4)
*
* z = _mm_mul_ps(x,x);
*/
- LLVMValueRef z = LLVMBuildMul(b, x_3, x_3, "z");
+ LLVMValueRef z = LLVMBuildFMul(b, x_3, x_3, "z");
/*
* _PS_CONST(coscof_p0, 2.443315711809948E-005);
@@ -1378,12 +1541,12 @@ lp_build_sin(struct lp_build_context *bld,
* y = *(v4sf*)_ps_coscof_p0;
* y = _mm_mul_ps(y, z);
*/
- LLVMValueRef y_3 = LLVMBuildMul(b, z, coscof_p0, "y_3");
- LLVMValueRef y_4 = LLVMBuildAdd(b, y_3, coscof_p1, "y_4");
- LLVMValueRef y_5 = LLVMBuildMul(b, y_4, z, "y_5");
- LLVMValueRef y_6 = LLVMBuildAdd(b, y_5, coscof_p2, "y_6");
- LLVMValueRef y_7 = LLVMBuildMul(b, y_6, z, "y_7");
- LLVMValueRef y_8 = LLVMBuildMul(b, y_7, z, "y_8");
+ LLVMValueRef y_3 = LLVMBuildFMul(b, z, coscof_p0, "y_3");
+ LLVMValueRef y_4 = LLVMBuildFAdd(b, y_3, coscof_p1, "y_4");
+ LLVMValueRef y_5 = LLVMBuildFMul(b, y_4, z, "y_5");
+ LLVMValueRef y_6 = LLVMBuildFAdd(b, y_5, coscof_p2, "y_6");
+ LLVMValueRef y_7 = LLVMBuildFMul(b, y_6, z, "y_7");
+ LLVMValueRef y_8 = LLVMBuildFMul(b, y_7, z, "y_8");
/*
@@ -1392,10 +1555,10 @@ lp_build_sin(struct lp_build_context *bld,
* y = _mm_add_ps(y, *(v4sf*)_ps_1);
*/
LLVMValueRef half = lp_build_const_v4sf(0.5);
- LLVMValueRef tmp = LLVMBuildMul(b, z, half, "tmp");
- LLVMValueRef y_9 = LLVMBuildSub(b, y_8, tmp, "y_8");
+ LLVMValueRef tmp = LLVMBuildFMul(b, z, half, "tmp");
+ LLVMValueRef y_9 = LLVMBuildFSub(b, y_8, tmp, "y_8");
LLVMValueRef one = lp_build_const_v4sf(1.0);
- LLVMValueRef y_10 = LLVMBuildAdd(b, y_9, one, "y_9");
+ LLVMValueRef y_10 = LLVMBuildFAdd(b, y_9, one, "y_9");
/*
* _PS_CONST(sincof_p0, -1.9515295891E-4);
@@ -1419,13 +1582,13 @@ lp_build_sin(struct lp_build_context *bld,
* y2 = _mm_add_ps(y2, x);
*/
- LLVMValueRef y2_3 = LLVMBuildMul(b, z, sincof_p0, "y2_3");
- LLVMValueRef y2_4 = LLVMBuildAdd(b, y2_3, sincof_p1, "y2_4");
- LLVMValueRef y2_5 = LLVMBuildMul(b, y2_4, z, "y2_5");
- LLVMValueRef y2_6 = LLVMBuildAdd(b, y2_5, sincof_p2, "y2_6");
- LLVMValueRef y2_7 = LLVMBuildMul(b, y2_6, z, "y2_7");
- LLVMValueRef y2_8 = LLVMBuildMul(b, y2_7, x_3, "y2_8");
- LLVMValueRef y2_9 = LLVMBuildAdd(b, y2_8, x_3, "y2_9");
+ LLVMValueRef y2_3 = LLVMBuildFMul(b, z, sincof_p0, "y2_3");
+ LLVMValueRef y2_4 = LLVMBuildFAdd(b, y2_3, sincof_p1, "y2_4");
+ LLVMValueRef y2_5 = LLVMBuildFMul(b, y2_4, z, "y2_5");
+ LLVMValueRef y2_6 = LLVMBuildFAdd(b, y2_5, sincof_p2, "y2_6");
+ LLVMValueRef y2_7 = LLVMBuildFMul(b, y2_6, z, "y2_7");
+ LLVMValueRef y2_8 = LLVMBuildFMul(b, y2_7, x_3, "y2_8");
+ LLVMValueRef y2_9 = LLVMBuildFAdd(b, y2_8, x_3, "y2_9");
/*
* select the correct result from the two polynoms
@@ -1481,7 +1644,7 @@ lp_build_cos(struct lp_build_context *bld,
*/
LLVMValueRef FOPi = lp_build_const_v4sf(1.27323954473516);
- LLVMValueRef scale_y = LLVMBuildMul(b, x_abs, FOPi, "scale_y");
+ LLVMValueRef scale_y = LLVMBuildFMul(b, x_abs, FOPi, "scale_y");
/*
* store the integer part of y in mm0
@@ -1561,9 +1724,9 @@ lp_build_cos(struct lp_build_context *bld,
* xmm2 = _mm_mul_ps(y, xmm2);
* xmm3 = _mm_mul_ps(y, xmm3);
*/
- LLVMValueRef xmm1 = LLVMBuildMul(b, y_2, DP1, "xmm1");
- LLVMValueRef xmm2 = LLVMBuildMul(b, y_2, DP2, "xmm2");
- LLVMValueRef xmm3 = LLVMBuildMul(b, y_2, DP3, "xmm3");
+ LLVMValueRef xmm1 = LLVMBuildFMul(b, y_2, DP1, "xmm1");
+ LLVMValueRef xmm2 = LLVMBuildFMul(b, y_2, DP2, "xmm2");
+ LLVMValueRef xmm3 = LLVMBuildFMul(b, y_2, DP3, "xmm3");
/*
* x = _mm_add_ps(x, xmm1);
@@ -1571,16 +1734,16 @@ lp_build_cos(struct lp_build_context *bld,
* x = _mm_add_ps(x, xmm3);
*/
- LLVMValueRef x_1 = LLVMBuildAdd(b, x_abs, xmm1, "x_1");
- LLVMValueRef x_2 = LLVMBuildAdd(b, x_1, xmm2, "x_2");
- LLVMValueRef x_3 = LLVMBuildAdd(b, x_2, xmm3, "x_3");
+ LLVMValueRef x_1 = LLVMBuildFAdd(b, x_abs, xmm1, "x_1");
+ LLVMValueRef x_2 = LLVMBuildFAdd(b, x_1, xmm2, "x_2");
+ LLVMValueRef x_3 = LLVMBuildFAdd(b, x_2, xmm3, "x_3");
/*
* Evaluate the first polynom (0 <= x <= Pi/4)
*
* z = _mm_mul_ps(x,x);
*/
- LLVMValueRef z = LLVMBuildMul(b, x_3, x_3, "z");
+ LLVMValueRef z = LLVMBuildFMul(b, x_3, x_3, "z");
/*
* _PS_CONST(coscof_p0, 2.443315711809948E-005);
@@ -1595,12 +1758,12 @@ lp_build_cos(struct lp_build_context *bld,
* y = *(v4sf*)_ps_coscof_p0;
* y = _mm_mul_ps(y, z);
*/
- LLVMValueRef y_3 = LLVMBuildMul(b, z, coscof_p0, "y_3");
- LLVMValueRef y_4 = LLVMBuildAdd(b, y_3, coscof_p1, "y_4");
- LLVMValueRef y_5 = LLVMBuildMul(b, y_4, z, "y_5");
- LLVMValueRef y_6 = LLVMBuildAdd(b, y_5, coscof_p2, "y_6");
- LLVMValueRef y_7 = LLVMBuildMul(b, y_6, z, "y_7");
- LLVMValueRef y_8 = LLVMBuildMul(b, y_7, z, "y_8");
+ LLVMValueRef y_3 = LLVMBuildFMul(b, z, coscof_p0, "y_3");
+ LLVMValueRef y_4 = LLVMBuildFAdd(b, y_3, coscof_p1, "y_4");
+ LLVMValueRef y_5 = LLVMBuildFMul(b, y_4, z, "y_5");
+ LLVMValueRef y_6 = LLVMBuildFAdd(b, y_5, coscof_p2, "y_6");
+ LLVMValueRef y_7 = LLVMBuildFMul(b, y_6, z, "y_7");
+ LLVMValueRef y_8 = LLVMBuildFMul(b, y_7, z, "y_8");
/*
@@ -1609,10 +1772,10 @@ lp_build_cos(struct lp_build_context *bld,
* y = _mm_add_ps(y, *(v4sf*)_ps_1);
*/
LLVMValueRef half = lp_build_const_v4sf(0.5);
- LLVMValueRef tmp = LLVMBuildMul(b, z, half, "tmp");
- LLVMValueRef y_9 = LLVMBuildSub(b, y_8, tmp, "y_8");
+ LLVMValueRef tmp = LLVMBuildFMul(b, z, half, "tmp");
+ LLVMValueRef y_9 = LLVMBuildFSub(b, y_8, tmp, "y_8");
LLVMValueRef one = lp_build_const_v4sf(1.0);
- LLVMValueRef y_10 = LLVMBuildAdd(b, y_9, one, "y_9");
+ LLVMValueRef y_10 = LLVMBuildFAdd(b, y_9, one, "y_9");
/*
* _PS_CONST(sincof_p0, -1.9515295891E-4);
@@ -1636,13 +1799,13 @@ lp_build_cos(struct lp_build_context *bld,
* y2 = _mm_add_ps(y2, x);
*/
- LLVMValueRef y2_3 = LLVMBuildMul(b, z, sincof_p0, "y2_3");
- LLVMValueRef y2_4 = LLVMBuildAdd(b, y2_3, sincof_p1, "y2_4");
- LLVMValueRef y2_5 = LLVMBuildMul(b, y2_4, z, "y2_5");
- LLVMValueRef y2_6 = LLVMBuildAdd(b, y2_5, sincof_p2, "y2_6");
- LLVMValueRef y2_7 = LLVMBuildMul(b, y2_6, z, "y2_7");
- LLVMValueRef y2_8 = LLVMBuildMul(b, y2_7, x_3, "y2_8");
- LLVMValueRef y2_9 = LLVMBuildAdd(b, y2_8, x_3, "y2_9");
+ LLVMValueRef y2_3 = LLVMBuildFMul(b, z, sincof_p0, "y2_3");
+ LLVMValueRef y2_4 = LLVMBuildFAdd(b, y2_3, sincof_p1, "y2_4");
+ LLVMValueRef y2_5 = LLVMBuildFMul(b, y2_4, z, "y2_5");
+ LLVMValueRef y2_6 = LLVMBuildFAdd(b, y2_5, sincof_p2, "y2_6");
+ LLVMValueRef y2_7 = LLVMBuildFMul(b, y2_6, z, "y2_7");
+ LLVMValueRef y2_8 = LLVMBuildFMul(b, y2_7, x_3, "y2_8");
+ LLVMValueRef y2_9 = LLVMBuildFAdd(b, y2_8, x_3, "y2_9");
/*
* select the correct result from the two polynoms
@@ -1695,6 +1858,8 @@ lp_build_exp(struct lp_build_context *bld,
/* log2(e) = 1/log(2) */
LLVMValueRef log2e = lp_build_const_vec(bld->type, 1.4426950408889634);
+ assert(lp_check_value(bld->type, x));
+
return lp_build_mul(bld, log2e, lp_build_exp2(bld, x));
}
@@ -1709,14 +1874,12 @@ lp_build_log(struct lp_build_context *bld,
/* log(2) */
LLVMValueRef log2 = lp_build_const_vec(bld->type, 0.69314718055994529);
+ assert(lp_check_value(bld->type, x));
+
return lp_build_mul(bld, log2, lp_build_exp2(bld, x));
}
-#define EXP_POLY_DEGREE 3
-#define LOG_POLY_DEGREE 5
-
-
/**
* Generate polynomial.
* Ex: coeffs[0] + x * coeffs[1] + x^2 * coeffs[2].
@@ -1731,6 +1894,8 @@ lp_build_polynomial(struct lp_build_context *bld,
LLVMValueRef res = NULL;
unsigned i;
+ assert(lp_check_value(bld->type, x));
+
/* TODO: optimize the constant case */
if(LLVMIsConstant(x))
debug_printf("%s: inefficient/imprecise constant arithmetic\n",
@@ -1802,6 +1967,8 @@ lp_build_exp2_approx(struct lp_build_context *bld,
LLVMValueRef expfpart = NULL;
LLVMValueRef res = NULL;
+ assert(lp_check_value(bld->type, x));
+
if(p_exp2_int_part || p_frac_part || p_exp2) {
/* TODO: optimize the constant case */
if(LLVMIsConstant(x))
@@ -1817,7 +1984,7 @@ lp_build_exp2_approx(struct lp_build_context *bld,
ipart = lp_build_floor(bld, x);
/* fpart = x - ipart */
- fpart = LLVMBuildSub(bld->builder, x, ipart, "");
+ fpart = LLVMBuildFSub(bld->builder, x, ipart, "");
}
if(p_exp2_int_part || p_exp2) {
@@ -1832,7 +1999,7 @@ lp_build_exp2_approx(struct lp_build_context *bld,
expfpart = lp_build_polynomial(bld, fpart, lp_build_exp2_polynomial,
Elements(lp_build_exp2_polynomial));
- res = LLVMBuildMul(bld->builder, expipart, expfpart, "");
+ res = LLVMBuildFMul(bld->builder, expipart, expfpart, "");
}
if(p_exp2_int_part)
@@ -1915,6 +2082,8 @@ lp_build_log2_approx(struct lp_build_context *bld,
LLVMValueRef logmant = NULL;
LLVMValueRef res = NULL;
+ assert(lp_check_value(bld->type, x));
+
if(p_exp || p_floor_log2 || p_log2) {
/* TODO: optimize the constant case */
if(LLVMIsConstant(x))
@@ -1945,9 +2114,9 @@ lp_build_log2_approx(struct lp_build_context *bld,
Elements(lp_build_log2_polynomial));
/* This effectively increases the polynomial degree by one, but ensures that log2(1) == 0*/
- logmant = LLVMBuildMul(bld->builder, logmant, LLVMBuildSub(bld->builder, mant, bld->one, ""), "");
+ logmant = LLVMBuildFMul(bld->builder, logmant, LLVMBuildFSub(bld->builder, mant, bld->one, ""), "");
- res = LLVMBuildAdd(bld->builder, logmant, logexp, "");
+ res = LLVMBuildFAdd(bld->builder, logmant, logexp, "");
}
if(p_exp) {
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_assert.c b/src/gallium/auxiliary/gallivm/lp_bld_assert.c
new file mode 100644
index 0000000000..f2ebd868a8
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/lp_bld_assert.c
@@ -0,0 +1,101 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "lp_bld_assert.h"
+#include "lp_bld_init.h"
+#include "lp_bld_printf.h"
+
+
+/**
+ * A call to lp_build_assert() will build a function call to this function.
+ */
+static void
+lp_assert(int condition, const char *msg)
+{
+ if (!condition) {
+ debug_printf("LLVM assertion '%s' failed!\n", msg);
+ assert(condition);
+ }
+}
+
+
+
+/**
+ * lp_build_assert.
+ *
+ * Build an assertion in LLVM IR by building a function call to the
+ * lp_assert() function above.
+ *
+ * \param condition should be an 'i1' or 'i32' value
+ * \param msg a string to print if the assertion fails.
+ */
+LLVMValueRef
+lp_build_assert(LLVMBuilderRef builder, LLVMValueRef condition,
+ const char *msg)
+{
+ LLVMModuleRef module;
+ LLVMTypeRef arg_types[2];
+ LLVMValueRef msg_string, assert_func, params[2], r;
+
+ module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(
+ LLVMGetInsertBlock(builder)));
+
+ msg_string = lp_build_const_string_variable(module, msg, strlen(msg) + 1);
+
+ arg_types[0] = LLVMInt32Type();
+ arg_types[1] = LLVMPointerType(LLVMInt8Type(), 0);
+
+ /* lookup the lp_assert function */
+ assert_func = LLVMGetNamedFunction(module, "lp_assert");
+
+ /* Create the assertion function if not found */
+ if (!assert_func) {
+ LLVMTypeRef func_type =
+ LLVMFunctionType(LLVMVoidType(), arg_types, 2, 0);
+
+ assert_func = LLVMAddFunction(module, "lp_assert", func_type);
+ LLVMSetFunctionCallConv(assert_func, LLVMCCallConv);
+ LLVMSetLinkage(assert_func, LLVMExternalLinkage);
+ LLVMAddGlobalMapping(lp_build_engine, assert_func,
+ func_to_pointer((func_pointer)lp_assert));
+ }
+ assert(assert_func);
+
+ /* build function call param list */
+ params[0] = LLVMBuildZExt(builder, condition, arg_types[0], "");
+ params[1] = LLVMBuildBitCast(builder, msg_string, arg_types[1], "");
+
+ /* check arg types */
+ assert(LLVMTypeOf(params[0]) == arg_types[0]);
+ assert(LLVMTypeOf(params[1]) == arg_types[1]);
+
+ r = LLVMBuildCall(builder, assert_func, params, 2, "");
+
+ return r;
+}
diff --git a/src/gallium/state_trackers/dri/drm/dri2.h b/src/gallium/auxiliary/gallivm/lp_bld_assert.h
index 07adfe4f6c..ddd879dc2c 100644
--- a/src/gallium/state_trackers/dri/drm/dri2.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_assert.h
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright 2009, VMware, Inc.
+ * Copyright 2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,13 +25,17 @@
*
**************************************************************************/
-#ifndef DRI2_H
-#define DRI2_H
+#ifndef LP_BLD_ASSERT_H
+#define LP_BLD_ASSERT_H
-#include "dri_drawable.h"
-#include "dri_wrapper.h"
-const __DRIconfig **
-dri2_init_screen(__DRIscreen * sPriv);
+#include "lp_bld.h"
+
+
+LLVMValueRef
+lp_build_assert(LLVMBuilderRef builder, LLVMValueRef condition,
+ const char *msg);
+
+
+#endif
-#endif /* DRI2_H */
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c
index 77012f1fac..8b477313d4 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_conv.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.c
@@ -117,8 +117,8 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
scale = (double)mask/ubound;
bias = (double)((unsigned long long)1 << (mantissa - n));
- res = LLVMBuildMul(builder, src, lp_build_const_vec(src_type, scale), "");
- res = LLVMBuildAdd(builder, res, lp_build_const_vec(src_type, bias), "");
+ res = LLVMBuildFMul(builder, src, lp_build_const_vec(src_type, scale), "");
+ res = LLVMBuildFAdd(builder, res, lp_build_const_vec(src_type, bias), "");
res = LLVMBuildBitCast(builder, res, int_vec_type, "");
if(dst_width > n) {
@@ -175,6 +175,8 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
double scale;
double bias;
+ assert(dst_type.floating);
+
mantissa = lp_mantissa(dst_type);
n = MIN2(mantissa, src_width);
@@ -199,8 +201,8 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
res = LLVMBuildBitCast(builder, res, vec_type, "");
- res = LLVMBuildSub(builder, res, bias_, "");
- res = LLVMBuildMul(builder, res, lp_build_const_vec(dst_type, scale), "");
+ res = LLVMBuildFSub(builder, res, bias_, "");
+ res = LLVMBuildFMul(builder, res, lp_build_const_vec(dst_type, scale), "");
return res;
}
@@ -296,7 +298,7 @@ lp_build_conv(LLVMBuilderRef builder,
if (dst_scale != 1.0) {
LLVMValueRef scale = lp_build_const_vec(tmp_type, dst_scale);
for(i = 0; i < num_tmps; ++i)
- tmp[i] = LLVMBuildMul(builder, tmp[i], scale, "");
+ tmp[i] = LLVMBuildFMul(builder, tmp[i], scale, "");
}
/* Use an equally sized integer for intermediate computations */
@@ -391,7 +393,7 @@ lp_build_conv(LLVMBuilderRef builder,
if (src_scale != 1.0) {
LLVMValueRef scale = lp_build_const_vec(tmp_type, 1.0/src_scale);
for(i = 0; i < num_tmps; ++i)
- tmp[i] = LLVMBuildMul(builder, tmp[i], scale, "");
+ tmp[i] = LLVMBuildFMul(builder, tmp[i], scale, "");
}
}
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
index 0f01fc1d75..247cb83ce6 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
@@ -240,7 +240,7 @@ lp_build_unpack_arith_rgba_aos(LLVMBuilderRef builder,
*/
if (normalized)
- scaled = LLVMBuildMul(builder, casted, LLVMConstVector(scales, 4), "");
+ scaled = LLVMBuildFMul(builder, casted, LLVMConstVector(scales, 4), "");
else
scaled = casted;
@@ -322,7 +322,7 @@ lp_build_pack_rgba_aos(LLVMBuilderRef builder,
}
if (normalized)
- scaled = LLVMBuildMul(builder, unswizzled, LLVMConstVector(scales, 4), "");
+ scaled = LLVMBuildFMul(builder, unswizzled, LLVMConstVector(scales, 4), "");
else
scaled = unswizzled;
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c
index 9f405921b0..c724a4453e 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c
@@ -197,7 +197,7 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
if (format_desc->channel[chan].normalized) {
double scale = 1.0 / ((1 << (format_desc->channel[chan].size - 1)) - 1);
LLVMValueRef scale_val = lp_build_const_vec(type, scale);
- input = LLVMBuildMul(builder, input, scale_val, "");
+ input = LLVMBuildFMul(builder, input, scale_val, "");
}
}
else {
@@ -227,7 +227,7 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
double scale = 1.0 / ((1 << (format_desc->channel[chan].size/2)) - 1);
LLVMValueRef scale_val = lp_build_const_vec(type, scale);
input = LLVMBuildSIToFP(builder, input, lp_build_vec_type(type), "");
- input = LLVMBuildMul(builder, input, scale_val, "");
+ input = LLVMBuildFMul(builder, input, scale_val, "");
}
else {
/* FIXME */
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c
index 69353dea09..60d8bcfa55 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_init.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c
@@ -45,6 +45,8 @@ static const struct debug_named_value lp_bld_debug_flags[] = {
{ "nopt", GALLIVM_DEBUG_NO_OPT, NULL },
DEBUG_NAMED_VALUE_END
};
+
+DEBUG_GET_ONCE_FLAGS_OPTION(gallivm_debug, "GALLIVM_DEBUG", lp_bld_debug_flags, 0)
#endif
@@ -89,7 +91,7 @@ void
lp_build_init(void)
{
#ifdef DEBUG
- gallivm_debug = debug_get_flags_option("GALLIVM_DEBUG", lp_bld_debug_flags, 0 );
+ gallivm_debug = debug_get_option_gallivm_debug();
#endif
lp_set_target_options();
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.h b/src/gallium/auxiliary/gallivm/lp_bld_init.h
index a32ced9b4c..f26fdac466 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_init.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_init.h
@@ -44,5 +44,7 @@ extern LLVMPassManagerRef lp_build_pass;
void
lp_build_init(void);
+extern void
+lp_func_delete_body(LLVMValueRef func);
#endif /* !LP_BLD_INIT_H */
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_logic.c b/src/gallium/auxiliary/gallivm/lp_bld_logic.c
index 39854e43b1..7d7db3b0d9 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_logic.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_logic.c
@@ -83,6 +83,8 @@ lp_build_compare(LLVMBuilderRef builder,
assert(func >= PIPE_FUNC_NEVER);
assert(func <= PIPE_FUNC_ALWAYS);
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
if(func == PIPE_FUNC_NEVER)
return zeros;
@@ -363,9 +365,55 @@ lp_build_cmp(struct lp_build_context *bld,
/**
+ * Return (mask & a) | (~mask & b);
+ */
+LLVMValueRef
+lp_build_select_bitwise(struct lp_build_context *bld,
+ LLVMValueRef mask,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ struct lp_type type = bld->type;
+ LLVMValueRef res;
+
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
+
+ if (a == b) {
+ return a;
+ }
+
+ if(type.floating) {
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
+ a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
+ b = LLVMBuildBitCast(bld->builder, b, int_vec_type, "");
+ }
+
+ a = LLVMBuildAnd(bld->builder, a, mask, "");
+
+ /* This often gets translated to PANDN, but sometimes the NOT is
+ * pre-computed and stored in another constant. The best strategy depends
+ * on available registers, so it is not a big deal -- hopefully LLVM does
+ * the right decision attending the rest of the program.
+ */
+ b = LLVMBuildAnd(bld->builder, b, LLVMBuildNot(bld->builder, mask, ""), "");
+
+ res = LLVMBuildOr(bld->builder, a, b, "");
+
+ if(type.floating) {
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ res = LLVMBuildBitCast(bld->builder, res, vec_type, "");
+ }
+
+ return res;
+}
+
+
+/**
* Return mask ? a : b;
*
- * mask is a bitwise mask, composed of 0 or ~0 for each element.
+ * mask is a bitwise mask, composed of 0 or ~0 for each element. Any other value
+ * will yield unpredictable results.
*/
LLVMValueRef
lp_build_select(struct lp_build_context *bld,
@@ -376,6 +424,9 @@ lp_build_select(struct lp_build_context *bld,
struct lp_type type = bld->type;
LLVMValueRef res;
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
+
if(a == b)
return a;
@@ -424,27 +475,7 @@ lp_build_select(struct lp_build_context *bld,
}
}
else {
- if(type.floating) {
- LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
- a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
- b = LLVMBuildBitCast(bld->builder, b, int_vec_type, "");
- }
-
- a = LLVMBuildAnd(bld->builder, a, mask, "");
-
- /* This often gets translated to PANDN, but sometimes the NOT is
- * pre-computed and stored in another constant. The best strategy depends
- * on available registers, so it is not a big deal -- hopefully LLVM does
- * the right decision attending the rest of the program.
- */
- b = LLVMBuildAnd(bld->builder, b, LLVMBuildNot(bld->builder, mask, ""), "");
-
- res = LLVMBuildOr(bld->builder, a, b, "");
-
- if(type.floating) {
- LLVMTypeRef vec_type = lp_build_vec_type(type);
- res = LLVMBuildBitCast(bld->builder, res, vec_type, "");
- }
+ res = lp_build_select_bitwise(bld, mask, a, b);
}
return res;
@@ -461,6 +492,9 @@ lp_build_select_aos(struct lp_build_context *bld,
const unsigned n = type.length;
unsigned i, j;
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
+
if(a == b)
return a;
if(cond[0] && cond[1] && cond[2] && cond[3])
@@ -516,7 +550,22 @@ lp_build_select_aos(struct lp_build_context *bld,
LLVMValueRef
lp_build_andc(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
{
+ const struct lp_type type = bld->type;
+
+ assert(lp_check_value(type, a));
+ assert(lp_check_value(type, b));
+
+ /* can't do bitwise ops on floating-point values */
+ if(type.floating) {
+ a = LLVMBuildBitCast(bld->builder, a, bld->int_vec_type, "");
+ b = LLVMBuildBitCast(bld->builder, b, bld->int_vec_type, "");
+ }
+
b = LLVMBuildNot(bld->builder, b, "");
b = LLVMBuildAnd(bld->builder, a, b, "");
+
+ if(type.floating) {
+ b = LLVMBuildBitCast(bld->builder, b, bld->vec_type, "");
+ }
return b;
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_logic.h b/src/gallium/auxiliary/gallivm/lp_bld_logic.h
index 29f9fc3b20..4e7b4c9938 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_logic.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_logic.h
@@ -63,6 +63,11 @@ lp_build_cmp(struct lp_build_context *bld,
LLVMValueRef a,
LLVMValueRef b);
+LLVMValueRef
+lp_build_select_bitwise(struct lp_build_context *bld,
+ LLVMValueRef mask,
+ LLVMValueRef a,
+ LLVMValueRef b);
LLVMValueRef
lp_build_select(struct lp_build_context *bld,
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
index 5a9488b5f7..6d5410d970 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
+++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
@@ -39,6 +39,7 @@
#include <llvm/Target/TargetOptions.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/JITEventListener.h>
+#include <llvm/Support/CommandLine.h>
#include "pipe/p_config.h"
#include "util/u_debug.h"
@@ -141,4 +142,35 @@ lp_set_target_options(void)
#if 0
llvm::UnsafeFPMath = true;
#endif
+
+#if 0
+ /*
+ * LLVM will generate MMX instructions for vectors <= 64 bits, leading to
+ * innefficient code, and in 32bit systems, to the corruption of the FPU
+ * stack given that it expects the user to generate the EMMS instructions.
+ *
+ * See also:
+ * - http://llvm.org/bugs/show_bug.cgi?id=3287
+ * - http://l4.me.uk/post/2009/06/07/llvm-wrinkle-3-configuration-what-configuration/
+ *
+ * XXX: Unfortunately this is not working.
+ */
+ static boolean first = FALSE;
+ if (first) {
+ static const char* options[] = {
+ "prog",
+ "-disable-mmx"
+ };
+ llvm::cl::ParseCommandLineOptions(2, const_cast<char**>(options));
+ first = FALSE;
+ }
+#endif
+}
+
+
+extern "C" void
+lp_func_delete_body(LLVMValueRef FF)
+{
+ llvm::Function *func = llvm::unwrap<llvm::Function>(FF);
+ func->deleteBody();
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_pack.c b/src/gallium/auxiliary/gallivm/lp_bld_pack.c
index 7748f8f099..b7b630f2e8 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_pack.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_pack.c
@@ -171,14 +171,13 @@ lp_build_unpack2(LLVMBuilderRef builder,
msb = lp_build_zero(src_type);
/* Interleave bits */
- if(util_cpu_caps.little_endian) {
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
*dst_lo = lp_build_interleave2(builder, src_type, src, msb, 0);
*dst_hi = lp_build_interleave2(builder, src_type, src, msb, 1);
- }
- else {
+#else
*dst_lo = lp_build_interleave2(builder, src_type, msb, src, 0);
*dst_hi = lp_build_interleave2(builder, src_type, msb, src, 1);
- }
+#endif
/* Cast the result into the new type (twice as wide) */
@@ -261,13 +260,14 @@ lp_build_pack2(LLVMBuilderRef builder,
#endif
LLVMTypeRef dst_vec_type = lp_build_vec_type(dst_type);
LLVMValueRef shuffle;
- LLVMValueRef res;
+ LLVMValueRef res = NULL;
assert(!src_type.floating);
assert(!dst_type.floating);
assert(src_type.width == dst_type.width * 2);
assert(src_type.length * 2 == dst_type.length);
+ /* Check for special cases first */
if(util_cpu_caps.has_sse2 && src_type.width * src_type.length == 128) {
switch(src_type.width) {
case 32:
@@ -283,8 +283,8 @@ lp_build_pack2(LLVMBuilderRef builder,
return lp_build_intrinsic_binary(builder, "llvm.x86.sse41.packusdw", dst_vec_type, lo, hi);
}
else {
- assert(0);
- return LLVMGetUndef(dst_vec_type);
+ /* use generic shuffle below */
+ res = NULL;
}
}
break;
@@ -310,10 +310,13 @@ lp_build_pack2(LLVMBuilderRef builder,
break;
}
- res = LLVMBuildBitCast(builder, res, dst_vec_type, "");
- return res;
+ if (res) {
+ res = LLVMBuildBitCast(builder, res, dst_vec_type, "");
+ return res;
+ }
}
+ /* generic shuffle */
lo = LLVMBuildBitCast(builder, lo, dst_vec_type, "");
hi = LLVMBuildBitCast(builder, hi, dst_vec_type, "");
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_quad.c b/src/gallium/auxiliary/gallivm/lp_bld_quad.c
index ca36046d22..7b1088939b 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_quad.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_quad.c
@@ -85,7 +85,7 @@ lp_build_scalar_ddx(struct lp_build_context *bld,
LLVMValueRef idx_right = LLVMConstInt(LLVMInt32Type(), LP_BLD_QUAD_TOP_RIGHT, 0);
LLVMValueRef a_left = LLVMBuildExtractElement(bld->builder, a, idx_left, "");
LLVMValueRef a_right = LLVMBuildExtractElement(bld->builder, a, idx_right, "");
- return LLVMBuildSub(bld->builder, a_right, a_left, "");
+ return lp_build_sub(bld, a_right, a_left);
}
@@ -97,5 +97,5 @@ lp_build_scalar_ddy(struct lp_build_context *bld,
LLVMValueRef idx_bottom = LLVMConstInt(LLVMInt32Type(), LP_BLD_QUAD_BOTTOM_LEFT, 0);
LLVMValueRef a_top = LLVMBuildExtractElement(bld->builder, a, idx_top, "");
LLVMValueRef a_bottom = LLVMBuildExtractElement(bld->builder, a, idx_bottom, "");
- return LLVMBuildSub(bld->builder, a_bottom, a_top, "");
+ return lp_build_sub(bld, a_bottom, a_top);
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
index 1a20d74cac..806c7d56a8 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -40,7 +40,6 @@
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_format.h"
-#include "util/u_cpu_detect.h"
#include "lp_bld_debug.h"
#include "lp_bld_type.h"
#include "lp_bld_const.h"
@@ -811,7 +810,7 @@ lp_build_minify(struct lp_build_sample_context *bld,
LLVMValueRef base_size,
LLVMValueRef level)
{
- LLVMValueRef size = LLVMBuildAShr(bld->builder, base_size, level, "minify");
+ LLVMValueRef size = LLVMBuildLShr(bld->builder, base_size, level, "minify");
size = lp_build_max(&bld->int_coord_bld, size, bld->int_coord_bld.one);
return size;
}
@@ -888,17 +887,17 @@ lp_build_lod_selector(struct lp_build_sample_context *bld,
/* Compute rho = max of all partial derivatives scaled by texture size.
* XXX this could be vectorized somewhat
*/
- rho = LLVMBuildMul(bld->builder,
+ rho = LLVMBuildFMul(bld->builder,
lp_build_max(float_bld, dsdx, dsdy),
lp_build_int_to_float(float_bld, width), "");
if (dims > 1) {
LLVMValueRef max;
- max = LLVMBuildMul(bld->builder,
+ max = LLVMBuildFMul(bld->builder,
lp_build_max(float_bld, dtdx, dtdy),
lp_build_int_to_float(float_bld, height), "");
rho = lp_build_max(float_bld, rho, max);
if (dims > 2) {
- max = LLVMBuildMul(bld->builder,
+ max = LLVMBuildFMul(bld->builder,
lp_build_max(float_bld, drdx, drdy),
lp_build_int_to_float(float_bld, depth), "");
rho = lp_build_max(float_bld, rho, max);
@@ -912,12 +911,12 @@ lp_build_lod_selector(struct lp_build_sample_context *bld,
if (lod_bias) {
lod_bias = LLVMBuildExtractElement(bld->builder, lod_bias,
index0, "");
- lod = LLVMBuildAdd(bld->builder, lod, lod_bias, "shader_lod_bias");
+ lod = LLVMBuildFAdd(bld->builder, lod, lod_bias, "shader_lod_bias");
}
}
/* add sampler lod bias */
- lod = LLVMBuildAdd(bld->builder, lod, sampler_lod_bias, "sampler_lod_bias");
+ lod = LLVMBuildFAdd(bld->builder, lod, sampler_lod_bias, "sampler_lod_bias");
/* clamp lod */
lod = lp_build_clamp(float_bld, lod, min_lod, max_lod);
@@ -1219,8 +1218,7 @@ lp_build_cube_ima(struct lp_build_context *coord_bld, LLVMValueRef coord)
/* ima = -0.5 / abs(coord); */
LLVMValueRef negHalf = lp_build_const_vec(coord_bld->type, -0.5);
LLVMValueRef absCoord = lp_build_abs(coord_bld, coord);
- LLVMValueRef ima = lp_build_mul(coord_bld, negHalf,
- lp_build_rcp(coord_bld, absCoord));
+ LLVMValueRef ima = lp_build_div(coord_bld, negHalf, absCoord);
return ima;
}
@@ -1841,7 +1839,11 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
unsigned i, j;
for(j = 0; j < h16.type.length; j += 4) {
- unsigned subindex = util_cpu_caps.little_endian ? 0 : 1;
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
+ unsigned subindex = 0;
+#else
+ unsigned subindex = 1;
+#endif
LLVMValueRef index;
index = LLVMConstInt(elem_type, j/2 + subindex, 0);
@@ -2029,6 +2031,8 @@ lp_build_sample_soa(LLVMBuilderRef builder,
debug_printf("Sample from %s\n", util_format_name(fmt));
}
+ assert(type.floating);
+
/* Setup our build context */
memset(&bld, 0, sizeof bld);
bld.builder = builder;
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index 21236839fb..0aa64affac 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -489,7 +489,7 @@ get_indirect_offsets(struct lp_build_tgsi_soa_context *bld,
int_vec_type, "");
/* addr_vec = addr_vec * 4 */
- addr_vec = lp_build_mul(&bld->base, addr_vec, vec4);
+ addr_vec = lp_build_mul(&bld->int_bld, addr_vec, vec4);
return addr_vec;
}
@@ -533,7 +533,7 @@ emit_fetch(
reg->Register.Index * 4 + swizzle);
/* index_vec = index_vec + addr_vec */
- index_vec = lp_build_add(&bld->base, index_vec, addr_vec);
+ index_vec = lp_build_add(&bld->int_bld, index_vec, addr_vec);
/* Gather values from the constant buffer */
res = build_gather(bld, bld->consts_ptr, index_vec);
@@ -612,11 +612,9 @@ emit_fetch(
case TGSI_UTIL_SIGN_SET:
/* TODO: Use bitwese OR for floating point */
res = lp_build_abs( &bld->base, res );
- res = LLVMBuildNeg( bld->base.builder, res, "" );
- break;
-
+ /* fall through */
case TGSI_UTIL_SIGN_TOGGLE:
- res = LLVMBuildNeg( bld->base.builder, res, "" );
+ res = lp_build_negate( &bld->base, res );
break;
case TGSI_UTIL_SIGN_KEEP:
@@ -773,7 +771,9 @@ emit_store(
addr = LLVMBuildExtractElement(bld->base.builder,
addr, LLVMConstInt(LLVMInt32Type(), 0, 0),
"");
- addr = lp_build_mul(&bld->base, addr, LLVMConstInt(LLVMInt32Type(), 4, 0));
+ addr = LLVMBuildMul(bld->base.builder,
+ addr, LLVMConstInt(LLVMInt32Type(), 4, 0),
+ "");
}
switch( reg->Register.File ) {
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 5275faa5e2..298f3d0a8b 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -557,6 +557,23 @@ print_temp(const struct tgsi_exec_machine *mach, uint index)
#endif
+void
+tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach,
+ unsigned num_bufs,
+ const void **bufs,
+ const unsigned *buf_sizes)
+{
+ unsigned i;
+
+ for (i = 0; i < num_bufs; i++) {
+ mach->Consts[i] = bufs[i];
+ mach->ConstsSize[i] = buf_sizes[i];
+ }
+}
+
+
+
+
/**
* Check if there's a potential src/dst register data dependency when
* using SOA execution.
@@ -632,6 +649,10 @@ tgsi_exec_machine_bind_shader(
util_init_math();
+ if (numSamplers) {
+ assert(samplers);
+ }
+
mach->Tokens = tokens;
mach->Samplers = samplers;
@@ -1040,6 +1061,8 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
{
uint i;
+ assert(swizzle < 4);
+
switch (file) {
case TGSI_FILE_CONSTANT:
for (i = 0; i < QUAD_SIZE; i++) {
@@ -1049,9 +1072,23 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
if (index->i[i] < 0) {
chan->u[i] = 0;
} else {
- const uint *p = (const uint *)mach->Consts[index2D->i[i]];
-
- chan->u[i] = p[index->i[i] * 4 + swizzle];
+ /* NOTE: copying the const value as a uint instead of float */
+ const uint constbuf = index2D->i[i];
+ const uint *buf = (const uint *)mach->Consts[constbuf];
+ const int pos = index->i[i] * 4 + swizzle;
+ /* const buffer bounds check */
+ if (pos < 0 || pos >= mach->ConstsSize[constbuf]) {
+ if (0) {
+ /* Debug: print warning */
+ static int count = 0;
+ if (count++ < 100)
+ debug_printf("TGSI Exec: const buffer index %d"
+ " out of bounds\n", pos);
+ }
+ chan->u[i] = 0;
+ }
+ else
+ chan->u[i] = buf[pos];
}
}
break;
@@ -1065,9 +1102,10 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i],
index2D->i[i], index->i[i]);
}*/
- chan->u[i] = mach->Inputs[index2D->i[i] *
- TGSI_EXEC_MAX_INPUT_ATTRIBS +
- index->i[i]].xyzw[swizzle].u[i];
+ int pos = index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i];
+ assert(pos >= 0);
+ assert(pos < Elements(mach->Inputs));
+ chan->u[i] = mach->Inputs[pos].xyzw[swizzle].u[i];
}
break;
@@ -1187,7 +1225,7 @@ fetch_source(const struct tgsi_exec_machine *mach,
index2.i[1] =
index2.i[2] =
index2.i[3] = reg->Indirect.Index;
-
+ assert(reg->Indirect.File == TGSI_FILE_ADDRESS);
/* get current value of address register[swizzle] */
swizzle = tgsi_util_get_src_register_swizzle( &reg->Indirect, CHAN_X );
fetch_src_file_channel(mach,
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
index ccf80ca6fd..6dee362d58 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -253,7 +253,10 @@ struct tgsi_exec_machine
struct tgsi_sampler **Samplers;
unsigned ImmLimit;
+
const void *Consts[PIPE_MAX_CONSTANT_BUFFERS];
+ unsigned ConstsSize[PIPE_MAX_CONSTANT_BUFFERS];
+
const struct tgsi_token *Tokens; /**< Declarations, instructions */
unsigned Processor; /**< TGSI_PROCESSOR_x */
@@ -367,6 +370,13 @@ tgsi_set_exec_mask(struct tgsi_exec_machine *mach,
}
+extern void
+tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach,
+ unsigned num_bufs,
+ const void **bufs,
+ const unsigned *buf_sizes);
+
+
#if defined __cplusplus
} /* extern "C" */
#endif
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
index 97148dbe23..acbff103ef 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
@@ -33,6 +33,10 @@
#include "tgsi_info.h"
#include "tgsi_iterate.h"
+
+DEBUG_GET_ONCE_BOOL_OPTION(print_sanity, "TGSI_PRINT_SANITY", FALSE)
+
+
typedef struct {
uint file : 28;
/* max 2 dimensions */
@@ -54,6 +58,8 @@ struct sanity_check_ctx
uint errors;
uint warnings;
uint implied_array_size;
+
+ boolean print;
};
static INLINE unsigned
@@ -148,6 +154,9 @@ report_error(
{
va_list args;
+ if (!ctx->print)
+ return;
+
debug_printf( "Error : " );
va_start( args, format );
_debug_vprintf( format, args );
@@ -164,6 +173,9 @@ report_warning(
{
va_list args;
+ if (!ctx->print)
+ return;
+
debug_printf( "Warning: " );
va_start( args, format );
_debug_vprintf( format, args );
@@ -539,6 +551,7 @@ tgsi_sanity_check(
ctx.errors = 0;
ctx.warnings = 0;
ctx.implied_array_size = 0;
+ ctx.print = debug_get_option_print_sanity();
if (!tgsi_iterate_shader( tokens, &ctx.iter ))
return FALSE;
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.h b/src/gallium/auxiliary/tgsi/tgsi_sanity.h
index 52263ff883..73f0f414e3 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sanity.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.h
@@ -35,7 +35,8 @@ extern "C" {
#endif
/* Check the given token stream for errors and common mistakes.
- * Diagnostic messages are printed out to the debug output.
+ * Diagnostic messages are printed out to the debug output, and is
+ * controlled by the debug option TGSI_PRINT_SANITY (default false).
* Returns TRUE if there are no errors, even though there could be some warnings.
*/
boolean
diff --git a/src/gallium/auxiliary/translate/translate.c b/src/gallium/auxiliary/translate/translate.c
index a9b7253bf4..fe638e211f 100644
--- a/src/gallium/auxiliary/translate/translate.c
+++ b/src/gallium/auxiliary/translate/translate.c
@@ -48,3 +48,8 @@ struct translate *translate_create( const struct translate_key *key )
return translate_generic_create( key );
}
+
+boolean translate_is_output_format_supported(enum pipe_format format)
+{
+ return translate_generic_is_output_format_supported(format);
+}
diff --git a/src/gallium/auxiliary/translate/translate.h b/src/gallium/auxiliary/translate/translate.h
index edd95e0788..eb6f2cc486 100644
--- a/src/gallium/auxiliary/translate/translate.h
+++ b/src/gallium/auxiliary/translate/translate.h
@@ -105,6 +105,8 @@ struct translate *translate_lookup_or_create( struct translate_context *tctx,
struct translate *translate_create( const struct translate_key *key );
+boolean translate_is_output_format_supported(enum pipe_format format);
+
static INLINE int translate_keysize( const struct translate_key *key )
{
return 2 * sizeof(int) + key->nr_elements * sizeof(struct translate_element);
@@ -138,5 +140,6 @@ struct translate *translate_sse2_create( const struct translate_key *key );
struct translate *translate_generic_create( const struct translate_key *key );
+boolean translate_generic_is_output_format_supported(enum pipe_format format);
#endif
diff --git a/src/gallium/auxiliary/translate/translate_generic.c b/src/gallium/auxiliary/translate/translate_generic.c
index 0e43a512ee..42cfd763e9 100644
--- a/src/gallium/auxiliary/translate/translate_generic.c
+++ b/src/gallium/auxiliary/translate/translate_generic.c
@@ -187,9 +187,15 @@ ATTRIB( R8G8B8_SNORM, 3, char, TO_8_SNORM )
ATTRIB( R8G8_SNORM, 2, char, TO_8_SNORM )
ATTRIB( R8_SNORM, 1, char, TO_8_SNORM )
-ATTRIB( A8R8G8B8_UNORM, 4, ubyte, TO_8_UNORM )
-/*ATTRIB( R8G8B8A8_UNORM, 4, ubyte, TO_8_UNORM )*/
-
+static void
+emit_A8R8G8B8_UNORM( const float *attrib, void *ptr)
+{
+ ubyte *out = (ubyte *)ptr;
+ out[0] = TO_8_UNORM(attrib[3]);
+ out[1] = TO_8_UNORM(attrib[0]);
+ out[2] = TO_8_UNORM(attrib[1]);
+ out[3] = TO_8_UNORM(attrib[2]);
+}
static void
emit_B8G8R8A8_UNORM( const float *attrib, void *ptr)
@@ -368,23 +374,23 @@ static void PIPE_CDECL generic_run_elts( struct translate *translate,
/* loop over vertex attributes (vertex shader inputs)
*/
for (i = 0; i < count; i++) {
- unsigned elt = *elts++;
+ const unsigned elt = *elts++;
for (attr = 0; attr < nr_attrs; attr++) {
float data[4];
- const uint8_t *src;
- unsigned index;
-
- char *dst = (vert +
- tg->attrib[attr].output_offset);
+ char *dst = vert + tg->attrib[attr].output_offset;
if (tg->attrib[attr].type == TRANSLATE_ELEMENT_NORMAL) {
+ const uint8_t *src;
+ unsigned index;
+
if (tg->attrib[attr].instance_divisor) {
index = instance_id / tg->attrib[attr].instance_divisor;
} else {
index = elt;
}
+ /* clamp to void going out of bounds */
index = MIN2(index, tg->attrib[attr].max_index);
src = tg->attrib[attr].input_ptr +
@@ -392,11 +398,23 @@ static void PIPE_CDECL generic_run_elts( struct translate *translate,
tg->attrib[attr].fetch( data, src, 0, 0 );
+ if (0)
+ debug_printf("Fetch elt attr %d from %p stride %d div %u max %u index %d: "
+ " %f, %f, %f, %f \n",
+ attr,
+ tg->attrib[attr].input_ptr,
+ tg->attrib[attr].input_stride,
+ tg->attrib[attr].instance_divisor,
+ tg->attrib[attr].max_index,
+ index,
+ data[0], data[1],data[2], data[3]);
} else {
data[0] = (float)instance_id;
}
- if (0) debug_printf("vert %d/%d attr %d: %f %f %f %f\n",
- i, elt, attr, data[0], data[1], data[2], data[3]);
+
+ if (0)
+ debug_printf("vert %d/%d attr %d: %f %f %f %f\n",
+ i, elt, attr, data[0], data[1], data[2], data[3]);
tg->attrib[attr].emit( data, dst );
}
@@ -425,29 +443,42 @@ static void PIPE_CDECL generic_run( struct translate *translate,
for (attr = 0; attr < nr_attrs; attr++) {
float data[4];
-
- char *dst = (vert +
- tg->attrib[attr].output_offset);
+ char *dst = vert + tg->attrib[attr].output_offset;
if (tg->attrib[attr].type == TRANSLATE_ELEMENT_NORMAL) {
const uint8_t *src;
+ unsigned index;
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;
+ index = instance_id / tg->attrib[attr].instance_divisor;
}
+ else {
+ index = elt;
+ }
+
+ /* clamp to void going out of bounds */
+ index = MIN2(index, tg->attrib[attr].max_index);
+
+ src = tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride * index;
tg->attrib[attr].fetch( data, src, 0, 0 );
+
+ if (0)
+ debug_printf("Fetch linear attr %d from %p stride %d index %d: "
+ " %f, %f, %f, %f \n",
+ attr,
+ tg->attrib[attr].input_ptr,
+ tg->attrib[attr].input_stride,
+ index,
+ data[0], data[1],data[2], data[3]);
} 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]);
+ if (0)
+ debug_printf("vert %d attr %d: %f %f %f %f\n",
+ i, attr, data[0], data[1], data[2], data[3]);
tg->attrib[attr].emit( data, dst );
}
@@ -523,3 +554,83 @@ struct translate *translate_generic_create( const struct translate_key *key )
return &tg->translate;
}
+
+boolean translate_generic_is_output_format_supported(enum pipe_format format)
+{
+ switch(format)
+ {
+ case PIPE_FORMAT_R64G64B64A64_FLOAT: return TRUE;
+ case PIPE_FORMAT_R64G64B64_FLOAT: return TRUE;
+ case PIPE_FORMAT_R64G64_FLOAT: return TRUE;
+ case PIPE_FORMAT_R64_FLOAT: return TRUE;
+
+ case PIPE_FORMAT_R32G32B32A32_FLOAT: return TRUE;
+ case PIPE_FORMAT_R32G32B32_FLOAT: return TRUE;
+ case PIPE_FORMAT_R32G32_FLOAT: return TRUE;
+ case PIPE_FORMAT_R32_FLOAT: return TRUE;
+
+ case PIPE_FORMAT_R32G32B32A32_USCALED: return TRUE;
+ case PIPE_FORMAT_R32G32B32_USCALED: return TRUE;
+ case PIPE_FORMAT_R32G32_USCALED: return TRUE;
+ case PIPE_FORMAT_R32_USCALED: return TRUE;
+
+ case PIPE_FORMAT_R32G32B32A32_SSCALED: return TRUE;
+ case PIPE_FORMAT_R32G32B32_SSCALED: return TRUE;
+ case PIPE_FORMAT_R32G32_SSCALED: return TRUE;
+ case PIPE_FORMAT_R32_SSCALED: return TRUE;
+
+ case PIPE_FORMAT_R32G32B32A32_UNORM: return TRUE;
+ case PIPE_FORMAT_R32G32B32_UNORM: return TRUE;
+ case PIPE_FORMAT_R32G32_UNORM: return TRUE;
+ case PIPE_FORMAT_R32_UNORM: return TRUE;
+
+ case PIPE_FORMAT_R32G32B32A32_SNORM: return TRUE;
+ case PIPE_FORMAT_R32G32B32_SNORM: return TRUE;
+ case PIPE_FORMAT_R32G32_SNORM: return TRUE;
+ case PIPE_FORMAT_R32_SNORM: return TRUE;
+
+ case PIPE_FORMAT_R16G16B16A16_USCALED: return TRUE;
+ case PIPE_FORMAT_R16G16B16_USCALED: return TRUE;
+ case PIPE_FORMAT_R16G16_USCALED: return TRUE;
+ case PIPE_FORMAT_R16_USCALED: return TRUE;
+
+ case PIPE_FORMAT_R16G16B16A16_SSCALED: return TRUE;
+ case PIPE_FORMAT_R16G16B16_SSCALED: return TRUE;
+ case PIPE_FORMAT_R16G16_SSCALED: return TRUE;
+ case PIPE_FORMAT_R16_SSCALED: return TRUE;
+
+ case PIPE_FORMAT_R16G16B16A16_UNORM: return TRUE;
+ case PIPE_FORMAT_R16G16B16_UNORM: return TRUE;
+ case PIPE_FORMAT_R16G16_UNORM: return TRUE;
+ case PIPE_FORMAT_R16_UNORM: return TRUE;
+
+ case PIPE_FORMAT_R16G16B16A16_SNORM: return TRUE;
+ case PIPE_FORMAT_R16G16B16_SNORM: return TRUE;
+ case PIPE_FORMAT_R16G16_SNORM: return TRUE;
+ case PIPE_FORMAT_R16_SNORM: return TRUE;
+
+ case PIPE_FORMAT_R8G8B8A8_USCALED: return TRUE;
+ case PIPE_FORMAT_R8G8B8_USCALED: return TRUE;
+ case PIPE_FORMAT_R8G8_USCALED: return TRUE;
+ case PIPE_FORMAT_R8_USCALED: return TRUE;
+
+ case PIPE_FORMAT_R8G8B8A8_SSCALED: return TRUE;
+ case PIPE_FORMAT_R8G8B8_SSCALED: return TRUE;
+ case PIPE_FORMAT_R8G8_SSCALED: return TRUE;
+ case PIPE_FORMAT_R8_SSCALED: return TRUE;
+
+ case PIPE_FORMAT_R8G8B8A8_UNORM: return TRUE;
+ case PIPE_FORMAT_R8G8B8_UNORM: return TRUE;
+ case PIPE_FORMAT_R8G8_UNORM: return TRUE;
+ case PIPE_FORMAT_R8_UNORM: return TRUE;
+
+ case PIPE_FORMAT_R8G8B8A8_SNORM: return TRUE;
+ case PIPE_FORMAT_R8G8B8_SNORM: return TRUE;
+ case PIPE_FORMAT_R8G8_SNORM: return TRUE;
+ case PIPE_FORMAT_R8_SNORM: return TRUE;
+
+ case PIPE_FORMAT_A8R8G8B8_UNORM: return TRUE;
+ case PIPE_FORMAT_B8G8R8A8_UNORM: return TRUE;
+ default: return FALSE;
+ }
+}
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 0d94aaae95..b5b86b7214 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -87,6 +87,7 @@ struct blitter_context_priv
void *dsa_write_depth_keep_stencil;
void *dsa_keep_depth_stencil;
void *dsa_keep_depth_write_stencil;
+ void *dsa_flush_depth_stencil;
void *velem_state;
@@ -156,6 +157,10 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
ctx->dsa_keep_depth_stencil =
pipe->create_depth_stencil_alpha_state(pipe, &dsa);
+ dsa.depth.writemask = 1;
+ ctx->dsa_flush_depth_stencil =
+ pipe->create_depth_stencil_alpha_state(pipe, &dsa);
+
dsa.depth.enabled = 1;
dsa.depth.writemask = 1;
dsa.depth.func = PIPE_FUNC_ALWAYS;
@@ -940,3 +945,42 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
UTIL_BLITTER_ATTRIB_NONE, NULL);
blitter_restore_CSOs(ctx);
}
+
+/* Clear a region of a depth stencil surface. */
+void util_blitter_flush_depth_stencil(struct blitter_context *blitter,
+ struct pipe_surface *dstsurf)
+{
+ struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+ struct pipe_context *pipe = ctx->base.pipe;
+ struct pipe_framebuffer_state fb_state;
+
+ assert(dstsurf->texture);
+ if (!dstsurf->texture)
+ return;
+
+ /* check the saved state */
+ blitter_check_saved_CSOs(ctx);
+ assert(blitter->saved_fb_state.nr_cbufs != ~0);
+
+ /* bind CSOs */
+ pipe->bind_blend_state(pipe, ctx->blend_keep_color);
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_flush_depth_stencil);
+
+ pipe->bind_rasterizer_state(pipe, ctx->rs_state);
+ pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0));
+ pipe->bind_vs_state(pipe, ctx->vs_col);
+ pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
+
+ /* set a framebuffer state */
+ fb_state.width = dstsurf->width;
+ fb_state.height = dstsurf->height;
+ fb_state.nr_cbufs = 0;
+ fb_state.cbufs[0] = 0;
+ fb_state.zsbuf = dstsurf;
+ pipe->set_framebuffer_state(pipe, &fb_state);
+
+ blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
+ blitter->draw_rectangle(blitter, 0, 0, dstsurf->width, dstsurf->height, 0,
+ UTIL_BLITTER_ATTRIB_NONE, NULL);
+ blitter_restore_CSOs(ctx);
+}
diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
index ba3f92eca8..f316587dea 100644
--- a/src/gallium/auxiliary/util/u_blitter.h
+++ b/src/gallium/auxiliary/util/u_blitter.h
@@ -200,6 +200,8 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height);
+void util_blitter_flush_depth_stencil(struct blitter_context *blitter,
+ struct pipe_surface *dstsurf);
/* The functions below should be used to save currently bound constant state
* objects inside a driver. The objects are automatically restored at the end
* of the util_blitter_{clear, copy_region, fill_region} functions and then
diff --git a/src/gallium/auxiliary/util/u_cpu_detect.c b/src/gallium/auxiliary/util/u_cpu_detect.c
index a08241971c..5056351307 100644
--- a/src/gallium/auxiliary/util/u_cpu_detect.c
+++ b/src/gallium/auxiliary/util/u_cpu_detect.c
@@ -38,7 +38,7 @@
#include "u_cpu_detect.h"
#if defined(PIPE_ARCH_PPC)
-#if defined(PIPE_OS_DARWIN)
+#if defined(PIPE_OS_APPLE)
#include <sys/sysctl.h>
#else
#include <signal.h>
@@ -73,9 +73,15 @@
#endif
+DEBUG_GET_ONCE_BOOL_OPTION(dump_cpu, "GALLIUM_DUMP_CPU", FALSE)
+
+
struct util_cpu_caps util_cpu_caps;
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
static int has_cpuid(void);
+#endif
+
#if defined(PIPE_ARCH_X86)
@@ -132,7 +138,7 @@ win32_sig_handler_sse(EXCEPTION_POINTERS* ep)
#endif /* PIPE_ARCH_X86 */
-#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_DARWIN)
+#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_APPLE)
static jmp_buf __lv_powerpc_jmpbuf;
static volatile sig_atomic_t __lv_powerpc_canjump = 0;
@@ -153,7 +159,7 @@ sigill_handler(int sig)
static void
check_os_altivec_support(void)
{
-#if defined(PIPE_OS_DARWIN)
+#if defined(PIPE_OS_APPLE)
int sels[2] = {CTL_HW, HW_VECTORUNIT};
int has_vu = 0;
int len = sizeof (has_vu);
@@ -166,8 +172,8 @@ check_os_altivec_support(void)
util_cpu_caps.has_altivec = 1;
}
}
-#else /* !PIPE_OS_DARWIN */
- /* no Darwin, do it the brute-force way */
+#else /* !PIPE_OS_APPLE */
+ /* not on Apple/Darwin, do it the brute-force way */
/* this is borrowed from the libmpeg2 library */
signal(SIGILL, sigill_handler);
if (setjmp(__lv_powerpc_jmpbuf)) {
@@ -184,7 +190,7 @@ check_os_altivec_support(void)
signal(SIGILL, SIG_DFL);
util_cpu_caps.has_altivec = 1;
}
-#endif /* PIPE_OS_DARWIN */
+#endif /* !PIPE_OS_APPLE */
}
#endif /* PIPE_ARCH_PPC */
@@ -385,23 +391,6 @@ util_cpu_detect(void)
memset(&util_cpu_caps, 0, sizeof util_cpu_caps);
- /* Check for arch type */
-#if defined(PIPE_ARCH_MIPS)
- util_cpu_caps.arch = UTIL_CPU_ARCH_MIPS;
-#elif defined(PIPE_ARCH_ALPHA)
- util_cpu_caps.arch = UTIL_CPU_ARCH_ALPHA;
-#elif defined(PIPE_ARCH_SPARC)
- util_cpu_caps.arch = UTIL_CPU_ARCH_SPARC;
-#elif defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
- util_cpu_caps.arch = UTIL_CPU_ARCH_X86;
- util_cpu_caps.little_endian = 1;
-#elif defined(PIPE_ARCH_PPC)
- util_cpu_caps.arch = UTIL_CPU_ARCH_POWERPC;
- util_cpu_caps.little_endian = 0;
-#else
- util_cpu_caps.arch = UTIL_CPU_ARCH_UNKNOWN;
-#endif
-
/* Count the number of CPUs in system */
#if defined(PIPE_OS_WINDOWS)
{
@@ -497,23 +486,24 @@ util_cpu_detect(void)
#endif /* PIPE_ARCH_PPC */
#ifdef DEBUG
- debug_printf("util_cpu_caps.arch = %i\n", util_cpu_caps.arch);
- debug_printf("util_cpu_caps.nr_cpus = %u\n", util_cpu_caps.nr_cpus);
-
- debug_printf("util_cpu_caps.x86_cpu_type = %u\n", util_cpu_caps.x86_cpu_type);
- debug_printf("util_cpu_caps.cacheline = %u\n", util_cpu_caps.cacheline);
-
- debug_printf("util_cpu_caps.has_tsc = %u\n", util_cpu_caps.has_tsc);
- debug_printf("util_cpu_caps.has_mmx = %u\n", util_cpu_caps.has_mmx);
- debug_printf("util_cpu_caps.has_mmx2 = %u\n", util_cpu_caps.has_mmx2);
- debug_printf("util_cpu_caps.has_sse = %u\n", util_cpu_caps.has_sse);
- debug_printf("util_cpu_caps.has_sse2 = %u\n", util_cpu_caps.has_sse2);
- debug_printf("util_cpu_caps.has_sse3 = %u\n", util_cpu_caps.has_sse3);
- debug_printf("util_cpu_caps.has_ssse3 = %u\n", util_cpu_caps.has_ssse3);
- debug_printf("util_cpu_caps.has_sse4_1 = %u\n", util_cpu_caps.has_sse4_1);
- debug_printf("util_cpu_caps.has_3dnow = %u\n", util_cpu_caps.has_3dnow);
- debug_printf("util_cpu_caps.has_3dnow_ext = %u\n", util_cpu_caps.has_3dnow_ext);
- debug_printf("util_cpu_caps.has_altivec = %u\n", util_cpu_caps.has_altivec);
+ if (debug_get_option_dump_cpu()) {
+ debug_printf("util_cpu_caps.nr_cpus = %u\n", util_cpu_caps.nr_cpus);
+
+ debug_printf("util_cpu_caps.x86_cpu_type = %u\n", util_cpu_caps.x86_cpu_type);
+ debug_printf("util_cpu_caps.cacheline = %u\n", util_cpu_caps.cacheline);
+
+ debug_printf("util_cpu_caps.has_tsc = %u\n", util_cpu_caps.has_tsc);
+ debug_printf("util_cpu_caps.has_mmx = %u\n", util_cpu_caps.has_mmx);
+ debug_printf("util_cpu_caps.has_mmx2 = %u\n", util_cpu_caps.has_mmx2);
+ debug_printf("util_cpu_caps.has_sse = %u\n", util_cpu_caps.has_sse);
+ debug_printf("util_cpu_caps.has_sse2 = %u\n", util_cpu_caps.has_sse2);
+ debug_printf("util_cpu_caps.has_sse3 = %u\n", util_cpu_caps.has_sse3);
+ debug_printf("util_cpu_caps.has_ssse3 = %u\n", util_cpu_caps.has_ssse3);
+ debug_printf("util_cpu_caps.has_sse4_1 = %u\n", util_cpu_caps.has_sse4_1);
+ debug_printf("util_cpu_caps.has_3dnow = %u\n", util_cpu_caps.has_3dnow);
+ debug_printf("util_cpu_caps.has_3dnow_ext = %u\n", util_cpu_caps.has_3dnow_ext);
+ debug_printf("util_cpu_caps.has_altivec = %u\n", util_cpu_caps.has_altivec);
+ }
#endif
util_cpu_detect_initialized = TRUE;
diff --git a/src/gallium/auxiliary/util/u_cpu_detect.h b/src/gallium/auxiliary/util/u_cpu_detect.h
index 4b3dc39c34..f3bef0993c 100644
--- a/src/gallium/auxiliary/util/u_cpu_detect.h
+++ b/src/gallium/auxiliary/util/u_cpu_detect.h
@@ -36,26 +36,15 @@
#define _UTIL_CPU_DETECT_H
#include "pipe/p_compiler.h"
-
-enum util_cpu_arch {
- UTIL_CPU_ARCH_UNKNOWN = 0,
- UTIL_CPU_ARCH_MIPS,
- UTIL_CPU_ARCH_ALPHA,
- UTIL_CPU_ARCH_SPARC,
- UTIL_CPU_ARCH_X86,
- UTIL_CPU_ARCH_POWERPC
-};
+#include "pipe/p_config.h"
struct util_cpu_caps {
- enum util_cpu_arch arch;
unsigned nr_cpus;
/* Feature flags */
int x86_cpu_type;
unsigned cacheline;
- unsigned little_endian:1;
-
unsigned has_tsc:1;
unsigned has_mmx:1;
unsigned has_mmx2:1;
diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c
index ad162558bc..504e6d2a18 100644
--- a/src/gallium/auxiliary/util/u_debug.c
+++ b/src/gallium/auxiliary/util/u_debug.c
@@ -88,7 +88,7 @@ debug_get_option_should_print(void)
* but its cool since we set first to false
*/
first = FALSE;
- value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", TRUE);
+ value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", FALSE);
/* XXX should we print this option? Currently it wont */
return value;
}
diff --git a/src/gallium/auxiliary/util/u_draw.h b/src/gallium/auxiliary/util/u_draw.h
new file mode 100644
index 0000000000..2a91ea0f9a
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_draw.h
@@ -0,0 +1,138 @@
+/**************************************************************************
+ *
+ * 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 U_DRAW_H
+#define U_DRAW_H
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_context.h"
+
+
+static INLINE void
+util_draw_init_info(struct pipe_draw_info *info)
+{
+ memset(info, 0, sizeof(*info));
+ info->instance_count = 1;
+ info->max_index = 0xffffffff;
+}
+
+
+static INLINE void
+util_draw_arrays(struct pipe_context *pipe, uint mode, uint start, uint count)
+{
+ struct pipe_draw_info info;
+
+ util_draw_init_info(&info);
+ info.mode = mode;
+ info.start = start;
+ info.count = count;
+ info.min_index = start;
+ info.max_index = start + count - 1;
+
+ pipe->draw_vbo(pipe, &info);
+}
+
+static INLINE void
+util_draw_elements(struct pipe_context *pipe, int index_bias,
+ uint mode, uint start, uint count)
+{
+ struct pipe_draw_info info;
+
+ util_draw_init_info(&info);
+ info.indexed = TRUE;
+ info.mode = mode;
+ info.start = start;
+ info.count = count;
+ info.index_bias = index_bias;
+
+ pipe->draw_vbo(pipe, &info);
+}
+
+static INLINE void
+util_draw_arrays_instanced(struct pipe_context *pipe,
+ uint mode, uint start, uint count,
+ uint start_instance,
+ uint instance_count)
+{
+ struct pipe_draw_info info;
+
+ util_draw_init_info(&info);
+ info.mode = mode;
+ info.start = start;
+ info.count = count;
+ info.start_instance = start_instance;
+ info.instance_count = instance_count;
+ info.min_index = start;
+ info.max_index = start + count - 1;
+
+ pipe->draw_vbo(pipe, &info);
+}
+
+static INLINE void
+util_draw_elements_instanced(struct pipe_context *pipe,
+ int index_bias,
+ uint mode, uint start, uint count,
+ uint start_instance,
+ uint instance_count)
+{
+ struct pipe_draw_info info;
+
+ util_draw_init_info(&info);
+ info.indexed = TRUE;
+ info.mode = mode;
+ info.start = start;
+ info.count = count;
+ info.index_bias = index_bias;
+ info.start_instance = start_instance;
+ info.instance_count = instance_count;
+
+ pipe->draw_vbo(pipe, &info);
+}
+
+static INLINE void
+util_draw_range_elements(struct pipe_context *pipe,
+ int index_bias,
+ uint min_index,
+ uint max_index,
+ uint mode, uint start, uint count)
+{
+ struct pipe_draw_info info;
+
+ util_draw_init_info(&info);
+ info.indexed = TRUE;
+ info.mode = mode;
+ info.start = start;
+ info.count = count;
+ info.index_bias = index_bias;
+ info.min_index = min_index;
+ info.max_index = max_index;
+
+ pipe->draw_vbo(pipe, &info);
+}
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c
index b37b48b5ae..0b6dc5880f 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.c
+++ b/src/gallium/auxiliary/util/u_draw_quad.c
@@ -60,7 +60,7 @@ util_draw_vertex_buffer(struct pipe_context *pipe,
/* note: vertex elements already set by caller */
/* draw */
- pipe->draw_arrays(pipe, prim_type, 0, num_verts);
+ util_draw_arrays(pipe, prim_type, 0, num_verts);
}
diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h
index 42eb184428..52994fe05c 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.h
+++ b/src/gallium/auxiliary/util/u_draw_quad.h
@@ -29,12 +29,18 @@
#define U_DRAWQUAD_H
+#include "pipe/p_compiler.h"
+#include "pipe/p_context.h"
+
+
#ifdef __cplusplus
extern "C" {
#endif
struct pipe_resource;
+#include "util/u_draw.h"
+
extern void
util_draw_vertex_buffer(struct pipe_context *pipe,
struct pipe_resource *vbuf, uint offset,
diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h
index 38254b1096..8e786a390a 100644
--- a/src/gallium/auxiliary/util/u_format.h
+++ b/src/gallium/auxiliary/util/u_format.h
@@ -631,6 +631,44 @@ util_format_has_alpha(enum pipe_format format)
}
/**
+ * Return the matching SRGB format, or PIPE_FORMAT_NONE if none.
+ */
+static INLINE enum pipe_format
+util_format_srgb(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_L8_UNORM:
+ return PIPE_FORMAT_L8_SRGB;
+ case PIPE_FORMAT_L8A8_UNORM:
+ return PIPE_FORMAT_L8A8_SRGB;
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ return PIPE_FORMAT_R8G8B8_SRGB;
+ case PIPE_FORMAT_A8B8G8R8_UNORM:
+ return PIPE_FORMAT_A8B8G8R8_SRGB;
+ case PIPE_FORMAT_X8B8G8R8_UNORM:
+ return PIPE_FORMAT_X8B8G8R8_SRGB;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ return PIPE_FORMAT_B8G8R8A8_SRGB;
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ return PIPE_FORMAT_B8G8R8X8_SRGB;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return PIPE_FORMAT_A8R8G8B8_SRGB;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ return PIPE_FORMAT_X8R8G8B8_SRGB;
+ case PIPE_FORMAT_DXT1_RGB:
+ return PIPE_FORMAT_DXT1_SRGB;
+ case PIPE_FORMAT_DXT1_RGBA:
+ return PIPE_FORMAT_DXT1_SRGBA;
+ case PIPE_FORMAT_DXT3_RGBA:
+ return PIPE_FORMAT_DXT3_SRGBA;
+ case PIPE_FORMAT_DXT5_RGBA:
+ return PIPE_FORMAT_DXT5_SRGBA;
+ default:
+ return PIPE_FORMAT_NONE;
+ }
+}
+
+/**
* Return the number of components stored.
* Formats with block size != 1x1 will always have 1 component (the block).
*/
diff --git a/src/gallium/auxiliary/util/u_format_other.c b/src/gallium/auxiliary/util/u_format_other.c
index 723fa8c3bf..fa42ec3713 100644
--- a/src/gallium/auxiliary/util/u_format_other.c
+++ b/src/gallium/auxiliary/util/u_format_other.c
@@ -121,6 +121,15 @@ util_format_r1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
* A.k.a. D3DFMT_CxV8U8
*/
+static uint8_t
+r8g8bx_derive(int16_t r, int16_t g)
+{
+ /* Derive blue from red and green components.
+ * Apparently, we must always use integers to perform calculations,
+ * otherwise the results won't match D3D's CxV8U8 definition.
+ */
+ return (uint8_t)sqrtf(0x7f * 0x7f - r * r - g * g) * 0xff / 0x7f;
+}
void
util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
@@ -145,7 +154,7 @@ util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
- dst[2] = sqrtf(1.0f - dst[0] * dst[0] - dst[1] * dst[1]); /* b */
+ dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */
dst[3] = 1.0f; /* a */
dst += 4;
}
@@ -177,7 +186,7 @@ util_format_r8g8bx_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_strid
dst[0] = (uint8_t)(((uint16_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint16_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */
- dst[2] = (uint8_t)sqrtf(0x7f*0x7f - r * r - g * g) * 0xff / 0x7f; /* b */
+ dst[2] = r8g8bx_derive(r, g); /* b */
dst[3] = 255; /* a */
dst += 4;
}
@@ -262,6 +271,6 @@ util_format_r8g8bx_snorm_fetch_rgba_float(float *dst, const uint8_t *src,
dst[0] = r * (1.0f/0x7f); /* r */
dst[1] = g * (1.0f/0x7f); /* g */
- dst[2] = sqrtf(1.0f - dst[0] * dst[0] - dst[1] * dst[1]); /* b */
+ dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */
dst[3] = 1.0f; /* a */
}
diff --git a/src/gallium/auxiliary/util/u_framebuffer.c b/src/gallium/auxiliary/util/u_framebuffer.c
index 768ae9ceb5..7803ec6a8b 100644
--- a/src/gallium/auxiliary/util/u_framebuffer.c
+++ b/src/gallium/auxiliary/util/u_framebuffer.c
@@ -85,9 +85,11 @@ util_copy_framebuffer_state(struct pipe_framebuffer_state *dst,
dst->width = src->width;
dst->height = src->height;
- for (i = 0; i < Elements(src->cbufs); i++) {
+ for (i = 0; i < src->nr_cbufs; i++)
pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
- }
+
+ for (i = src->nr_cbufs; i < dst->nr_cbufs; i++)
+ pipe_surface_reference(&dst->cbufs[i], NULL);
dst->nr_cbufs = src->nr_cbufs;
diff --git a/src/gallium/auxiliary/util/u_mempool.c b/src/gallium/auxiliary/util/u_mempool.c
index 84e2a34acc..1f336b39a1 100644
--- a/src/gallium/auxiliary/util/u_mempool.c
+++ b/src/gallium/auxiliary/util/u_mempool.c
@@ -126,7 +126,6 @@ void util_mempool_set_thread_safety(struct util_mempool *pool,
pool->threading = threading;
if (threading) {
- pipe_mutex_init(pool->mutex);
pool->malloc = util_mempool_malloc_mt;
pool->free = util_mempool_free_mt;
} else {
@@ -152,6 +151,8 @@ void util_mempool_create(struct util_mempool *pool,
make_empty_list(&pool->list);
+ pipe_mutex_init(pool->mutex);
+
util_mempool_set_thread_safety(pool, threading);
}
@@ -164,6 +165,5 @@ void util_mempool_destroy(struct util_mempool *pool)
FREE(page);
}
- if (pool->threading)
- pipe_mutex_destroy(pool->mutex);
+ pipe_mutex_destroy(pool->mutex);
}
diff --git a/src/gallium/auxiliary/util/u_network.c b/src/gallium/auxiliary/util/u_network.c
index 87ee0e4768..77f2c5fc7d 100644
--- a/src/gallium/auxiliary/util/u_network.c
+++ b/src/gallium/auxiliary/util/u_network.c
@@ -6,7 +6,7 @@
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
# include <winsock2.h>
# include <windows.h>
-#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_APPLE)
+#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_CYGWIN)
# include <sys/socket.h>
# include <netinet/in.h>
# include <unistd.h>
diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h
index 3ebef9fb74..5f113f742b 100644
--- a/src/gallium/auxiliary/util/u_pack_color.h
+++ b/src/gallium/auxiliary/util/u_pack_color.h
@@ -425,6 +425,53 @@ util_pack_color(const float rgba[4], enum pipe_format format, union util_color *
}
}
+/* Integer versions of util_pack_z and util_pack_z_stencil - useful for
+ * constructing clear masks.
+ */
+static INLINE uint
+util_pack_uint_z(enum pipe_format format, unsigned z)
+{
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ return z & 0xffff;
+ case PIPE_FORMAT_Z32_UNORM:
+ case PIPE_FORMAT_Z32_FLOAT:
+ return z;
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ return z & 0xffffff;
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ return (z & 0xffffff) << 8;
+ case PIPE_FORMAT_S8_USCALED:
+ return 0;
+ default:
+ debug_print_format("gallium: unhandled format in util_pack_z()", format);
+ assert(0);
+ return 0;
+ }
+}
+
+static INLINE uint
+util_pack_uint_z_stencil(enum pipe_format format, double z, uint s)
+{
+ unsigned packed = util_pack_uint_z(format, z);
+
+ s &= 0xff;
+
+ switch (format) {
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ return packed | (s << 24);
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+ return packed | s;
+ case PIPE_FORMAT_S8_USCALED:
+ return packed | s;
+ default:
+ return packed;
+ }
+}
+
+
/**
* Note: it's assumed that z is in [0,1]
diff --git a/src/gallium/auxiliary/util/u_prim.h b/src/gallium/auxiliary/util/u_prim.h
index 606b9b5c6b..3c851f7340 100644
--- a/src/gallium/auxiliary/util/u_prim.h
+++ b/src/gallium/auxiliary/util/u_prim.h
@@ -108,6 +108,20 @@ static INLINE boolean u_trim_pipe_prim( unsigned pipe_prim, unsigned *nr )
ok = (*nr >= 4);
*nr -= (*nr % 2);
break;
+ case PIPE_PRIM_LINES_ADJACENCY:
+ ok = (*nr >= 4);
+ *nr -= (*nr % 4);
+ break;
+ case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+ ok = (*nr >= 4);
+ break;
+ case PIPE_PRIM_TRIANGLES_ADJACENCY:
+ ok = (*nr >= 6);
+ *nr -= (*nr % 5);
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+ ok = (*nr >= 4);
+ break;
default:
ok = 0;
break;
diff --git a/src/gallium/auxiliary/util/u_split_prim.h b/src/gallium/auxiliary/util/u_split_prim.h
new file mode 100644
index 0000000000..206e1ec311
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_split_prim.h
@@ -0,0 +1,105 @@
+/* Originally written by Ben Skeggs for the nv50 driver*/
+#include <pipe/p_defines.h>
+
+struct util_split_prim {
+ void *priv;
+ void (*emit)(void *priv, unsigned start, unsigned count);
+ void (*edge)(void *priv, boolean enabled);
+
+ unsigned mode;
+ unsigned start;
+ unsigned p_start;
+ unsigned p_end;
+
+ uint repeat_first:1;
+ uint close_first:1;
+ uint edgeflag_off:1;
+};
+
+static INLINE void
+util_split_prim_init(struct util_split_prim *s,
+ unsigned mode, unsigned start, unsigned count)
+{
+ if (mode == PIPE_PRIM_LINE_LOOP) {
+ s->mode = PIPE_PRIM_LINE_STRIP;
+ s->close_first = 1;
+ } else {
+ s->mode = mode;
+ s->close_first = 0;
+ }
+ s->start = start;
+ s->p_start = start;
+ s->p_end = start + count;
+ s->edgeflag_off = 0;
+ s->repeat_first = 0;
+}
+
+static INLINE boolean
+util_split_prim_next(struct util_split_prim *s, unsigned max_verts)
+{
+ int repeat = 0;
+
+ if (s->repeat_first) {
+ s->emit(s->priv, s->start, 1);
+ max_verts--;
+ if (s->edgeflag_off) {
+ s->edge(s->priv, TRUE);
+ s->edgeflag_off = FALSE;
+ }
+ }
+
+ if (s->p_start + s->close_first + max_verts >= s->p_end) {
+ s->emit(s->priv, s->p_start, s->p_end - s->p_start);
+ if (s->close_first)
+ s->emit(s->priv, s->start, 1);
+ return TRUE;
+ }
+
+ switch (s->mode) {
+ case PIPE_PRIM_LINES:
+ max_verts &= ~1;
+ break;
+ case PIPE_PRIM_LINE_STRIP:
+ repeat = 1;
+ break;
+ case PIPE_PRIM_POLYGON:
+ max_verts--;
+ s->emit(s->priv, s->p_start, max_verts);
+ s->edge(s->priv, FALSE);
+ s->emit(s->priv, s->p_start + max_verts, 1);
+ s->p_start += max_verts;
+ s->repeat_first = TRUE;
+ s->edgeflag_off = TRUE;
+ return FALSE;
+ case PIPE_PRIM_TRIANGLES:
+ max_verts = max_verts - (max_verts % 3);
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ /* to ensure winding stays correct, always split
+ * on an even number of generated triangles
+ */
+ max_verts = max_verts & ~1;
+ repeat = 2;
+ break;
+ case PIPE_PRIM_TRIANGLE_FAN:
+ s->repeat_first = TRUE;
+ repeat = 1;
+ break;
+ case PIPE_PRIM_QUADS:
+ max_verts &= ~3;
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ max_verts &= ~1;
+ repeat = 2;
+ break;
+ case PIPE_PRIM_POINTS:
+ break;
+ default:
+ /* TODO: implement adjacency primitives */
+ assert(0);
+ }
+
+ s->emit (s->priv, s->p_start, max_verts);
+ s->p_start += (max_verts - repeat);
+ return FALSE;
+}
diff --git a/src/gallium/auxiliary/util/u_sse.h b/src/gallium/auxiliary/util/u_sse.h
index e2a8491e62..87959ab0aa 100644
--- a/src/gallium/auxiliary/util/u_sse.h
+++ b/src/gallium/auxiliary/util/u_sse.h
@@ -41,7 +41,6 @@
#if defined(PIPE_ARCH_SSE)
-#include <xmmintrin.h>
#include <emmintrin.h>
@@ -72,6 +71,35 @@ _mm_castps_si128(__m128 a)
#endif /* defined(_MSC_VER) && _MSC_VER < 1500 */
+
+#if defined(PIPE_ARCH_SSSE3)
+
+#include <tmmintrin.h>
+
+#else /* !PIPE_ARCH_SSSE3 */
+
+#include <emmintrin.h>
+
+/**
+ * Describe _mm_shuffle_epi8() with gcc extended inline assembly, for cases
+ * where -mssse3 is not supported/enabled.
+ *
+ * MSVC will never get in here as its intrinsics support do not rely on
+ * compiler command line options.
+ */
+static __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_shuffle_epi8(__m128i a, __m128i mask)
+{
+ __m128i result;
+ __asm__("pshufb %1, %0"
+ : "=x" (result)
+ : "xm" (mask), "0" (a));
+ return result;
+}
+
+#endif /* !PIPE_ARCH_SSSE3 */
+
+
#endif /* PIPE_ARCH_X86 || PIPE_ARCH_X86_64 */
#endif /* U_SSE_H_ */
diff --git a/src/gallium/auxiliary/util/u_staging.c b/src/gallium/auxiliary/util/u_staging.c
new file mode 100644
index 0000000000..607c31f5ee
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_staging.c
@@ -0,0 +1,95 @@
+#include "util/u_staging.h"
+#include "pipe/p_context.h"
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+
+static void
+util_staging_resource_template(struct pipe_resource *pt, unsigned width, unsigned height, unsigned depth, struct pipe_resource *template)
+{
+ memset(template, 0, sizeof(struct pipe_resource));
+ if(pt->target != PIPE_BUFFER && depth <= 1)
+ template->target = PIPE_TEXTURE_2D;
+ else
+ template->target = pt->target;
+ template->format = pt->format;
+ template->width0 = width;
+ template->height0 = height;
+ template->depth0 = depth;
+ template->last_level = 0;
+ template->nr_samples = pt->nr_samples;
+ template->bind = 0;
+ template->usage = PIPE_USAGE_STAGING;
+ template->flags = 0;
+}
+
+struct util_staging_transfer *
+util_staging_transfer_new(struct pipe_context *pipe,
+ struct pipe_resource *pt,
+ struct pipe_subresource sr,
+ unsigned usage,
+ const struct pipe_box *box,
+ bool direct)
+{
+ struct pipe_screen *pscreen = pipe->screen;
+ struct util_staging_transfer *tx;
+ struct pipe_resource staging_resource_template;
+
+ tx = CALLOC_STRUCT(util_staging_transfer);
+ if (!tx)
+ return NULL;
+
+ pipe_resource_reference(&tx->base.resource, pt);
+ tx->base.sr = sr;
+ tx->base.usage = usage;
+ tx->base.box = *box;
+
+ if (direct)
+ {
+ tx->staging_resource = pt;
+ return tx;
+ }
+
+ util_staging_resource_template(pt, box->width, box->height, box->depth, &staging_resource_template);
+ tx->staging_resource = pscreen->resource_create(pscreen, &staging_resource_template);
+ if (!tx->staging_resource)
+ {
+ pipe_resource_reference(&tx->base.resource, NULL);
+ FREE(tx);
+ return NULL;
+ }
+
+ if (usage & PIPE_TRANSFER_READ)
+ {
+ struct pipe_subresource dstsr;
+ unsigned zi;
+ dstsr.face = 0;
+ dstsr.level = 0;
+ for(zi = 0; zi < box->depth; ++zi)
+ pipe->resource_copy_region(pipe, tx->staging_resource, dstsr, 0, 0, 0, tx->base.resource, sr, box->x, box->y, box->z + zi, box->width, box->height);
+ }
+
+ return tx;
+}
+
+void
+util_staging_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx)
+{
+ struct util_staging_transfer *tx = (struct util_staging_transfer *)ptx;
+
+ if (tx->staging_resource != tx->base.resource)
+ {
+ if(tx->base.usage & PIPE_TRANSFER_WRITE) {
+ struct pipe_subresource srcsr;
+ unsigned zi;
+ srcsr.face = 0;
+ srcsr.level = 0;
+ for(zi = 0; zi < tx->base.box.depth; ++zi)
+ pipe->resource_copy_region(pipe, tx->base.resource, tx->base.sr, tx->base.box.x, tx->base.box.y, tx->base.box.z + zi, tx->staging_resource, srcsr, 0, 0, 0, tx->base.box.width, tx->base.box.height);
+ }
+
+ pipe_resource_reference(&tx->staging_resource, NULL);
+ }
+
+ pipe_resource_reference(&ptx->resource, NULL);
+ FREE(ptx);
+}
diff --git a/src/gallium/auxiliary/util/u_staging.h b/src/gallium/auxiliary/util/u_staging.h
new file mode 100644
index 0000000000..602faa2971
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_staging.h
@@ -0,0 +1,37 @@
+/* Direct3D 10/11 has no concept of transfers. Applications instead
+ * create resources with a STAGING or DYNAMIC usage, copy between them
+ * and the real resource and use Map to map the STAGING/DYNAMIC resource.
+ *
+ * This util module allows to implement Gallium drivers as a Direct3D
+ * driver would be implemented: transfers allocate a resource with
+ * PIPE_USAGE_STAGING, and copy the data between it and the real resource
+ * with resource_copy_region.
+ */
+
+#ifndef U_STAGING_H
+#define U_STAGING_H
+
+#include "pipe/p_state.h"
+
+struct util_staging_transfer {
+ struct pipe_transfer base;
+
+ /* if direct, same as base.resource, otherwise the temporary staging resource */
+ struct pipe_resource *staging_resource;
+};
+
+/* user must be stride, slice_stride and offset */
+/* pt->usage == PIPE_USAGE_DYNAMIC should be a good value to pass for direct */
+/* staging resource is currently created with PIPE_USAGE_DYNAMIC */
+struct util_staging_transfer *
+util_staging_transfer_new(struct pipe_context *pipe,
+ struct pipe_resource *pt,
+ struct pipe_subresource sr,
+ unsigned usage,
+ const struct pipe_box *box,
+ bool direct);
+
+void
+util_staging_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx);
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_surfaces.c b/src/gallium/auxiliary/util/u_surfaces.c
index b5d21570d5..7733ad24d0 100644
--- a/src/gallium/auxiliary/util/u_surfaces.c
+++ b/src/gallium/auxiliary/util/u_surfaces.c
@@ -3,40 +3,22 @@
#include "util/u_inlines.h"
#include "util/u_memory.h"
-/* TODO: ouch, util_hash_table should do these by default when passed a null function pointer
- * this indirect function call is quite bad
- */
-static unsigned
-hash(void *key)
-{
- return (unsigned)(uintptr_t)key;
-}
-
-static int
-compare(void *key1, void *key2)
-{
- return (unsigned)(uintptr_t)key1 - (unsigned)(uintptr_t)key2;
-}
-
struct pipe_surface *
util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags)
{
struct pipe_surface *ps;
- void *key = NULL;
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
- { /* or 2D array */
- if(!us->u.table)
- us->u.table = util_hash_table_create(hash, compare);
- key = (void *)(uintptr_t)(((zslice + face) << 8) | level);
- /* TODO: ouch, should have a get-reference function...
- * also, shouldn't allocate a two-pointer structure for each item... */
- ps = util_hash_table_get(us->u.table, key);
+ { /* or 2D array */
+ if(!us->u.hash)
+ us->u.hash = cso_hash_create();
+
+ ps = cso_hash_iter_data(cso_hash_find(us->u.hash, ((zslice + face) << 8) | level));
}
else
{
if(!us->u.array)
- us->u.array = CALLOC(pt->last_level + 1, sizeof(struct pipe_surface *));
+ us->u.array = CALLOC(pt->last_level + 1, sizeof(struct pipe_surface *));
ps = us->u.array[level];
}
@@ -54,7 +36,7 @@ util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, str
ps->offset = ~0;
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
- util_hash_table_set(us->u.table, key, ps);
+ cso_hash_insert(us->u.hash, ((zslice + face) << 8) | level, ps);
else
us->u.array[level] = ps;
@@ -66,47 +48,44 @@ util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps)
{
struct pipe_resource *pt = ps->texture;
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
- { /* or 2D array */
- void* key = (void*)(uintptr_t)(((ps->zslice + ps->face) << 8) | ps->level);
- util_hash_table_remove(us->u.table, key);
+ { /* or 2D array */
+ cso_hash_erase(us->u.hash, cso_hash_find(us->u.hash, ((ps->zslice + ps->face) << 8) | ps->level));
}
else
us->u.array[ps->level] = 0;
}
-static enum pipe_error
-util_surfaces_destroy_callback(void *key, void *value, void *data)
-{
- void (*destroy_surface) (struct pipe_surface * ps) = data;
- destroy_surface((struct pipe_surface *)value);
- return PIPE_OK;
-}
-
void
util_surfaces_destroy(struct util_surfaces *us, struct pipe_resource *pt, void (*destroy_surface) (struct pipe_surface *))
{
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
- { /* or 2D array */
- if(us->u.table)
+ { /* or 2D array */
+ if(us->u.hash)
{
- util_hash_table_foreach(us->u.table, util_surfaces_destroy_callback, destroy_surface);
- util_hash_table_destroy(us->u.table);
- us->u.table = NULL;
+ struct cso_hash_iter iter;
+ iter = cso_hash_first_node(us->u.hash);
+ while (!cso_hash_iter_is_null(iter)) {
+ destroy_surface(cso_hash_iter_data(iter));
+ iter = cso_hash_iter_next(iter);
+ }
+
+ cso_hash_delete(us->u.hash);
+ us->u.hash = NULL;
}
}
else
{
if(us->u.array)
{
- unsigned i;
- for(i = 0; i < pt->last_level; ++i)
- {
- struct pipe_surface *ps = us->u.array[i];
- if(ps)
- destroy_surface(ps);
- }
- FREE(us->u.array);
- us->u.array = NULL;
+ unsigned i;
+ for(i = 0; i <= pt->last_level; ++i)
+ {
+ struct pipe_surface *ps = us->u.array[i];
+ if(ps)
+ destroy_surface(ps);
+ }
+ FREE(us->u.array);
+ us->u.array = NULL;
}
}
}
diff --git a/src/gallium/auxiliary/util/u_surfaces.h b/src/gallium/auxiliary/util/u_surfaces.h
index 0195bf5afb..af978c7057 100644
--- a/src/gallium/auxiliary/util/u_surfaces.h
+++ b/src/gallium/auxiliary/util/u_surfaces.h
@@ -4,15 +4,15 @@
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "util/u_atomic.h"
-
-struct util_hash_table;
+#include "cso_cache/cso_hash.h"
struct util_surfaces
{
union
{
- struct util_hash_table *table;
+ struct cso_hash *hash;
struct pipe_surface **array;
+ void* pv;
} u;
};
@@ -35,6 +35,18 @@ util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size, struct
return util_surfaces_do_get(us, surface_struct_size, pscreen, pt, face, level, zslice, flags);
}
+static INLINE struct pipe_surface *
+util_surfaces_peek(struct util_surfaces *us, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice)
+{
+ if(!us->u.pv)
+ return 0;
+
+ if(unlikely(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE))
+ return cso_hash_iter_data(cso_hash_find(us->u.hash, ((zslice + face) << 8) | level));
+ else
+ return us->u.array[level];
+}
+
void util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps);
static INLINE void
diff --git a/src/gallium/docs/d3d11ddi.txt b/src/gallium/docs/d3d11ddi.txt
index 0954c2926d..f8155c828b 100644
--- a/src/gallium/docs/d3d11ddi.txt
+++ b/src/gallium/docs/d3d11ddi.txt
@@ -66,9 +66,6 @@ Unordered access view: view supporting random read/write access (usually from co
clear
+ Gallium supports clearing both render targets and depth/stencil with a single call
-draw_range_elements
- + Gallium supports indexed draw with explicit range
-
fence_signalled
fence_finish
+ D3D10/D3D11 don't appear to support explicit fencing; queries can often substitute though, and flushing is supported
@@ -271,31 +268,27 @@ Dispatch (D3D11 only)
DispatchIndirect (D3D11 only)
- Gallium does not support compute shaders
-Draw -> draw_arrays
+Draw -> draw_vbo
! D3D11 sets primitive modes separately with IaSetTopology: it's not obvious which is better
DrawAuto -> draw_auto
-DrawIndexed -> draw_elements
+DrawIndexed -> draw_vbo
! D3D11 sets primitive modes separately with IaSetTopology: it's not obvious which is better
- * may want to add a separate set_index_buffer
- - Gallium lacks base vertex for indexed draw calls
- + D3D11 lacks draw_range_elements functionality, which is required for OpenGL
+ + D3D11 lacks explicit range, which is required for OpenGL
-DrawIndexedInstanced -> draw_elements_instanced
+DrawIndexedInstanced -> draw_vbo
! D3D11 sets primitive modes separately with IaSetTopology: it's not obvious which is better
- * may want to add a separate set_index_buffer
- - Gallium lacks base vertex for indexed draw calls
-DrawIndexedInstancedIndirect (D3D11 only) -> call draw_elements_instanced multiple times in software
- # this allows to use an hardware buffer to specify the parameters for multiple draw_elements_instanced calls
+DrawIndexedInstancedIndirect (D3D11 only)
+ # this allows to use an hardware buffer to specify the parameters for multiple draw_vbo calls
- Gallium does not support draw call parameter buffers and indirect draw
-DrawInstanced -> draw_arrays_instanced
+DrawInstanced -> draw_vbo
! D3D11 sets primitive modes separately with IaSetTopology: it's not obvious which is better
-DrawInstancedIndirect (D3D11 only) -> call draw_arrays_instanced multiple times in software
- # this allows to use an hardware buffer to specify the parameters for multiple draw_arrays_instanced calls
+DrawInstancedIndirect (D3D11 only)
+ # this allows to use an hardware buffer to specify the parameters for multiple draw_vbo calls
- Gallium does not support draw call parameter buffers and indirect draws
DsSetConstantBuffers (D3D11 only)
@@ -332,10 +325,9 @@ HsSetShaderResources (D3D11 only)
HsSetShaderWithIfaces (D3D11 only)
- Gallium does not support hull shaders
-IaSetIndexBuffer
- ! Gallium passes this to the draw_elements or draw_elements_instanced calls
+IaSetIndexBuffer -> set_index_buffer
+ Gallium supports 8-bit indices
- ! the D3D11 interface allows index-size-unaligned byte offsets into index buffers; it's not clear whether they actually work
+ # the D3D11 interface allows index-size-unaligned byte offsets into the index buffer; most drivers will abort with an assertion
IaSetInputLayout -> bind_vertex_elements_state
diff --git a/src/gallium/docs/source/conf.py b/src/gallium/docs/source/conf.py
index ccc84405c4..0846e7d0ec 100644
--- a/src/gallium/docs/source/conf.py
+++ b/src/gallium/docs/source/conf.py
@@ -22,7 +22,7 @@ sys.path.append(os.path.abspath('exts'))
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.pngmath', 'tgsi']
+extensions = ['sphinx.ext.pngmath', 'formatting']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -38,7 +38,7 @@ master_doc = 'index'
# General information about the project.
project = u'Gallium'
-copyright = u'2009, VMWare, X.org, Nouveau'
+copyright = u'2009, VMware, X.org, Nouveau'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -176,7 +176,7 @@ htmlhelp_basename = 'Galliumdoc'
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'Gallium.tex', u'Gallium Documentation',
- u'VMWare, X.org, Nouveau', 'manual'),
+ u'VMware, X.org, Nouveau', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst
index 4e35a4c408..f241411a00 100644
--- a/src/gallium/docs/source/context.rst
+++ b/src/gallium/docs/source/context.rst
@@ -45,6 +45,7 @@ buffers, surfaces) are bound to the driver.
* ``set_vertex_buffers``
+* ``set_index_buffer``
Non-CSO State
^^^^^^^^^^^^^
@@ -132,50 +133,26 @@ this surface need not be bound to the framebuffer.
Drawing
^^^^^^^
-``draw_arrays`` draws a specified primitive.
+``draw_vbo`` draws a specified primitive. The primitive mode and other
+properties are described by ``pipe_draw_info``.
-This command is equivalent to calling ``draw_arrays_instanced``
-with ``startInstance`` set to 0 and ``instanceCount`` set to 1.
+The ``mode``, ``start``, and ``count`` fields of ``pipe_draw_info`` specify the
+the mode of the primitive and the vertices to be fetched, in the range between
+``start`` to ``start``+``count``-1, inclusive.
-``draw_elements`` draws a specified primitive using an optional
-index buffer.
+Every instance with instanceID in the range between ``start_instance`` and
+``start_instance``+``instance_count``-1, inclusive, will be drawn.
-This command is equivalent to calling ``draw_elements_instanced``
-with ``startInstance`` set to 0 and ``instanceCount`` set to 1.
+All vertex indices must fall inside the range given by ``min_index`` and
+``max_index``. In case non-indexed draw, ``min_index`` should be set to
+``start`` and ``max_index`` should be set to ``start``+``count``-1.
-``draw_range_elements``
+``index_bias`` is a value added to every vertex index before fetching vertex
+attributes. It does not affect ``min_index`` and ``max_index``.
-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.
-
-``indexBias`` is a value which is added to every index read from the index
-buffer before fetching vertex attributes.
-
-``minIndex`` and ``maxIndex`` describe minimum and maximum index contained in
-the index buffer.
+If there is an index buffer bound, and ``indexed`` field is true, all vertex
+indices will be looked up in the index buffer. ``min_index``, ``max_index``,
+and ``index_bias`` apply after index lookup.
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
diff --git a/src/gallium/docs/source/cso/rasterizer.rst b/src/gallium/docs/source/cso/rasterizer.rst
index ad1612f93e..ee3419ccfc 100644
--- a/src/gallium/docs/source/cso/rasterizer.rst
+++ b/src/gallium/docs/source/cso/rasterizer.rst
@@ -126,11 +126,15 @@ sprite_coord_enable
Specifies if a texture unit has its texture coordinates replaced or not. This
is a packed bitfield containing the enable for all texcoords -- if all bits
-are zero, point sprites are effectively disabled. If any bit is set, then
-point_smooth and point_quad_rasterization are ignored; point smoothing is
-disabled and points are always rasterized as quads. If enabled, the four
-vertices of the resulting quad will be assigned texture coordinates,
-according to sprite_coord_mode.
+are zero, point sprites are effectively disabled.
+
+If any bit is set, then point_smooth MUST be disabled (there are no
+round sprites) and point_quad_rasterization MUST be true (sprites are
+always rasterized as quads). Any mismatch between these states should
+be considered a bug in the state-tracker.
+
+If enabled, the four vertices of the resulting quad will be assigned
+texture coordinates, according to sprite_coord_mode.
sprite_coord_mode
^^^^^^^^^^^^^^^^^
@@ -141,20 +145,23 @@ have coordinates (0,0,0,1). For PIPE_SPRITE_COORD_UPPER_LEFT, the upper-left
vertex will have coordinates (0,0,0,1).
This state is used by :ref:`Draw` to generate texcoords.
-.. note::
-
- When geometry shaders are available, a special geometry shader could be
- used instead of this functionality, to convert incoming points into quads
- with the proper texture coordinates.
-
point_quad_rasterization
^^^^^^^^^^^^^^^^^^^^^^^^
-Determines if points should be rasterized as quads or points. Certain APIs,
-like Direct3D, always use quad rasterization for points, regardless of
-whether point sprites are enabled or not. If this state is enabled, point
-smoothing and antialiasing are disabled. If it is disabled, point sprite
-coordinates are not generated.
+Determines if points should be rasterized according to quad or point
+rasterization rules.
+
+OpenGL actually has quite different rasterization rules for points and
+point sprites - hence this indicates if points should be rasterized as
+points or according to point sprite (which decomposes them into quads,
+basically) rules.
+
+Additionally Direct3D will always use quad rasterization rules for
+points, regardless of whether point sprites are enabled or not.
+
+If this state is enabled, point smoothing and antialiasing are
+disabled. If it is disabled, point sprite coordinates are not
+generated.
.. note::
diff --git a/src/gallium/docs/source/debugging.rst b/src/gallium/docs/source/debugging.rst
new file mode 100644
index 0000000000..42bda5aee9
--- /dev/null
+++ b/src/gallium/docs/source/debugging.rst
@@ -0,0 +1,101 @@
+Debugging
+=========
+
+Debugging utilities in gallium.
+
+Debug Variables
+^^^^^^^^^^^^^^^
+
+All drivers respond to a set of common debug environment variables, as well as
+some driver-specific variables. Set them as normal environment variables for
+the platform or operating system you are running. For example, for Linux this
+can be done by typing "export var=value" into a console and then running the
+program from that console.
+
+Common
+""""""
+
+.. envvar:: GALLIUM_PRINT_OPTIONS <bool> (false)
+
+This option controls if the debug variables should be printed to stderr. This
+is probably the most useful variable, since it allows you to find which
+variables a driver uses.
+
+.. envvar:: GALLIUM_RBUG <bool> (false)
+
+Controls if the :ref:`rbug` should be used.
+
+.. envvar:: GALLIUM_TRACE <string> ("")
+
+If set, this variable will cause the :ref:`Trace` output to be written to the
+specified file. Paths may be relative or absolute; relative paths are relative
+to the working directory. For example, setting it to "trace.xml" will cause
+the trace to be written to a file of the same name in the working directory.
+
+.. envvar:: GALLIUM_DUMP_CPU <bool> (false)
+
+Dump information about the current CPU that the driver is running on.
+
+.. envvar:: TGSI_PRINT_SANITY <bool> (false)
+
+Gallium has a built-in shader sanity checker. This option controls whether
+the shader sanity checker prints its warnings and errors to stderr.
+
+.. envvar:: DRAW_USE_LLVM <bool> (false)
+
+Whether the :ref:`Draw` module will attempt to use LLVM for vertex and geometry shaders.
+
+
+State tracker-specific
+""""""""""""""""""""""
+
+.. envvar:: ST_DEBUG <flags> (0x0)
+
+Debug :ref:`flags` for the GL state tracker.
+
+
+Driver-specific
+"""""""""""""""
+
+.. envvar:: I915_DEBUG <flags> (0x0)
+
+Debug :ref:`flags` for the i915 driver.
+
+.. envvar:: I915_NO_HW <bool> (false)
+
+Stop the i915 driver from submitting commands to the hardware.
+
+.. envvar:: I915_DUMP_CMD <bool> (false)
+
+Dump all commands going to the hardware.
+
+.. envvar:: LP_DEBUG <flags> (0x0)
+
+Debug :ref:`flags` for the llvmpipe driver.
+
+.. envvar:: LP_NUM_THREADS <int> (number of CPUs)
+
+Number of threads that the llvmpipe driver should use.
+
+
+.. _flags:
+
+Flags
+"""""
+
+The variables of type "flags" all take a string with comma-separated flags to
+enable different debugging for different parts of the drivers or state
+tracker. If set to "help", the driver will print a list of flags which the
+variable accepts. Order does not matter.
+
+
+.. _rbug:
+
+Remote Debugger
+^^^^^^^^^^^^^^^
+
+The remote debugger, commonly known as rbug, allows for runtime inspections of
+:ref:`Context`, :ref:`Screen`, :ref:`Resource` and :ref:`Shader` objects; and
+pausing and stepping of :ref:`Draw` calls. Is used with rbug-gui which is
+hosted outside of the main mesa repository. rbug is can be used over a network
+connection, so the debugger does not need to be on the same machine.
diff --git a/src/gallium/docs/source/distro.rst b/src/gallium/docs/source/distro.rst
index 6ba5a056f4..70d75b51e6 100644
--- a/src/gallium/docs/source/distro.rst
+++ b/src/gallium/docs/source/distro.rst
@@ -51,10 +51,10 @@ nVidia nv50
Driver for the nVidia nv50 family of GPUs.
-VMWare SVGA
+VMware SVGA
^^^^^^^^^^^
-Driver for VMWare virtualized guest operating system graphics processing.
+Driver for VMware virtualized guest operating system graphics processing.
ATI r300
^^^^^^^^
@@ -74,6 +74,11 @@ Trace
Wrapper driver. Trace dumps an XML record of the calls made to the
:ref:`Context` and :ref:`Screen` objects that it wraps.
+Rbug
+^^^^
+
+Wrapper driver. :ref:`rbug` driver used with stand alone rbug-gui.
+
State Trackers
--------------
diff --git a/src/gallium/docs/source/exts/formatting.py b/src/gallium/docs/source/exts/formatting.py
new file mode 100644
index 0000000000..14865f3603
--- /dev/null
+++ b/src/gallium/docs/source/exts/formatting.py
@@ -0,0 +1,31 @@
+# formatting.py
+# Sphinx extension providing formatting for Gallium-specific data
+# (c) Corbin Simpson 2010
+# Public domain to the extent permitted; contact author for special licensing
+
+import docutils.nodes
+import sphinx.addnodes
+
+def parse_envvar(env, sig, signode):
+ envvar, t, default = sig.split(" ", 2)
+ envvar = envvar.strip().upper()
+ t = " Type: %s" % t.strip(" <>").lower()
+ default = " Default: %s" % default.strip(" ()")
+ signode += sphinx.addnodes.desc_name(envvar, envvar)
+ signode += sphinx.addnodes.desc_type(t, t)
+ signode += sphinx.addnodes.desc_annotation(default, default)
+ return envvar
+
+def parse_opcode(env, sig, signode):
+ opcode, desc = sig.split("-", 1)
+ opcode = opcode.strip().upper()
+ desc = " (%s)" % desc.strip()
+ signode += sphinx.addnodes.desc_name(opcode, opcode)
+ signode += sphinx.addnodes.desc_annotation(desc, desc)
+ return opcode
+
+def setup(app):
+ app.add_description_unit("envvar", "envvar", "%s (environment variable)",
+ parse_envvar)
+ app.add_description_unit("opcode", "opcode", "%s (TGSI opcode)",
+ parse_opcode)
diff --git a/src/gallium/docs/source/exts/tgsi.py b/src/gallium/docs/source/exts/tgsi.py
deleted file mode 100644
index e92cd5c4d1..0000000000
--- a/src/gallium/docs/source/exts/tgsi.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# tgsi.py
-# Sphinx extension providing formatting for TGSI opcodes
-# (c) Corbin Simpson 2010
-
-import docutils.nodes
-import sphinx.addnodes
-
-def parse_opcode(env, sig, signode):
- opcode, desc = sig.split("-", 1)
- opcode = opcode.strip().upper()
- desc = " (%s)" % desc.strip()
- signode += sphinx.addnodes.desc_name(opcode, opcode)
- signode += sphinx.addnodes.desc_annotation(desc, desc)
- return opcode
-
-def setup(app):
- app.add_description_unit("opcode", "opcode", "%s (TGSI opcode)", parse_opcode)
diff --git a/src/gallium/docs/source/index.rst b/src/gallium/docs/source/index.rst
index 54bc883fce..6c19842dac 100644
--- a/src/gallium/docs/source/index.rst
+++ b/src/gallium/docs/source/index.rst
@@ -12,6 +12,7 @@ Contents:
:maxdepth: 2
intro
+ debugging
tgsi
screen
context
diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h
index bbb112fd33..a8cdde34aa 100644
--- a/src/gallium/drivers/cell/common.h
+++ b/src/gallium/drivers/cell/common.h
@@ -230,7 +230,7 @@ struct cell_command_rasterizer
{
opcode_t opcode; /**< CELL_CMD_STATE_RASTERIZER */
struct pipe_rasterizer_state rasterizer;
- uint32_t pad[1];
+ /*uint32_t pad[1];*/
};
diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h
index 07b6eebc69..d1aee62ba1 100644
--- a/src/gallium/drivers/cell/ppu/cell_context.h
+++ b/src/gallium/drivers/cell/ppu/cell_context.h
@@ -132,6 +132,7 @@ struct cell_context
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
uint num_vertex_buffers;
+ struct pipe_index_buffer index_buffer;
ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS];
ubyte *zsbuf_map;
@@ -154,7 +155,7 @@ struct cell_context
struct vertex_info vertex_info;
/** Mapped constant buffers */
- void *mapped_constants[PIPE_SHADER_TYPES];
+ const void *mapped_constants[PIPE_SHADER_TYPES];
PIPE_ALIGN_VAR(16) struct cell_spu_function_info spu_functions;
diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
index 6a1e4d8a64..4adef5b8c0 100644
--- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
+++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
@@ -56,16 +56,11 @@
* XXX should the element buffer be specified/bound with a separate function?
*/
static void
-cell_draw_range_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned min_index,
- unsigned max_index,
- unsigned mode, unsigned start, unsigned count)
+cell_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct cell_context *cell = cell_context(pipe);
struct draw_context *draw = cell->draw;
+ void *mapped_indices = NULL;
unsigned i;
if (cell->dirty)
@@ -83,18 +78,20 @@ cell_draw_range_elements(struct pipe_context *pipe,
draw_set_mapped_vertex_buffer(draw, i, buf);
}
/* Map index buffer, if present */
- if (indexBuffer) {
- void *mapped_indexes = cell_resource(indexBuffer)->data;
- draw_set_mapped_element_buffer(draw, indexSize, indexBias, mapped_indexes);
- }
- else {
- /* no index/element buffer */
- draw_set_mapped_element_buffer(draw, 0, 0, NULL);
+ if (info->indexed && cell->index_buffer.buffer) {
+ mapped_indices = cell_resource(cell->index_buffer.buffer)->data;
+ mapped_indices += cell->index_buffer.offset;
}
+ draw_set_mapped_element_buffer_range(draw, (mapped_indices) ?
+ lp->index_buffer.index_size : 0,
+ info->index_bias,
+ info->min_index,
+ info->max_index,
+ mapped_indices);
/* draw! */
- draw_arrays(draw, mode, start, count);
+ draw_arrays(draw, info->mode, info->start, info->count);
/*
* unmap vertex/index buffers - will cause draw module to flush
@@ -102,7 +99,7 @@ cell_draw_range_elements(struct pipe_context *pipe,
for (i = 0; i < cell->num_vertex_buffers; i++) {
draw_set_mapped_vertex_buffer(draw, i, NULL);
}
- if (indexBuffer) {
+ if (mapped_indices) {
draw_set_mapped_element_buffer(draw, 0, 0, NULL);
}
@@ -115,32 +112,9 @@ cell_draw_range_elements(struct pipe_context *pipe,
}
-static void
-cell_draw_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned mode, unsigned start, unsigned count)
-{
- cell_draw_range_elements( pipe, indexBuffer,
- indexSize, indexBias,
- 0, 0xffffffff,
- mode, start, count );
-}
-
-
-static void
-cell_draw_arrays(struct pipe_context *pipe, unsigned mode,
- unsigned start, unsigned count)
-{
- cell_draw_elements(pipe, NULL, 0, 0, mode, start, count);
-}
-
-
void
cell_init_draw_functions(struct cell_context *cell)
{
- cell->pipe.draw_arrays = cell_draw_arrays;
- cell->pipe.draw_elements = cell_draw_elements;
- cell->pipe.draw_range_elements = cell_draw_range_elements;
+ cell->pipe.draw_vbo = cell_draw_vbo;
}
diff --git a/src/gallium/drivers/cell/ppu/cell_fence.c b/src/gallium/drivers/cell/ppu/cell_fence.c
index 34ca864155..e7c9fc46d9 100644
--- a/src/gallium/drivers/cell/ppu/cell_fence.c
+++ b/src/gallium/drivers/cell/ppu/cell_fence.c
@@ -87,6 +87,7 @@ struct cell_buffer_node
};
+#if 0
static void
cell_add_buffer_to_list(struct cell_context *cell,
struct cell_buffer_list *list,
@@ -100,6 +101,7 @@ cell_add_buffer_to_list(struct cell_context *cell,
list->head = node;
}
}
+#endif
/**
@@ -113,7 +115,7 @@ cell_free_fenced_buffers(struct cell_context *cell,
struct cell_buffer_list *list)
{
if (list->head) {
- struct pipe_screen *ps = cell->pipe.screen;
+ /*struct pipe_screen *ps = cell->pipe.screen;*/
struct cell_buffer_node *node;
cell_fence_finish(cell, &list->fence);
@@ -146,7 +148,7 @@ cell_free_fenced_buffers(struct cell_context *cell,
void
cell_add_fenced_textures(struct cell_context *cell)
{
- struct cell_buffer_list *list = &cell->fenced_buffers[cell->cur_batch];
+ /*struct cell_buffer_list *list = &cell->fenced_buffers[cell->cur_batch];*/
uint i;
for (i = 0; i < cell->num_textures; i++) {
diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c
index 03f84d295b..223adda48f 100644
--- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c
+++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c
@@ -281,7 +281,7 @@ cell_set_fragment_sampler_views(struct pipe_context *pipe,
struct pipe_resource *new_tex = new_view ? new_view->texture : NULL;
pipe_sampler_view_reference(&cell->fragment_sampler_views[i],
- views[i]);
+ new_view);
pipe_resource_reference((struct pipe_resource **) &cell->texture[i],
(struct pipe_resource *) new_tex);
diff --git a/src/gallium/drivers/cell/ppu/cell_state_vertex.c b/src/gallium/drivers/cell/ppu/cell_state_vertex.c
index 9510ea9ac2..4e3701cd0a 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_vertex.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_vertex.c
@@ -36,7 +36,7 @@
#include "draw/draw_context.h"
-void *
+static void *
cell_create_vertex_elements_state(struct pipe_context *pipe,
unsigned count,
const struct pipe_vertex_element *attribs)
@@ -51,7 +51,7 @@ cell_create_vertex_elements_state(struct pipe_context *pipe,
return velems;
}
-void
+static void
cell_bind_vertex_elements_state(struct pipe_context *pipe,
void *velems)
{
@@ -66,7 +66,7 @@ cell_bind_vertex_elements_state(struct pipe_context *pipe,
draw_set_vertex_elements(cell->draw, cell_velems->count, cell_velems->velem);
}
-void
+static void
cell_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)
{
FREE( velems );
@@ -91,10 +91,26 @@ cell_set_vertex_buffers(struct pipe_context *pipe,
}
+static void
+cell_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ if (ib)
+ memcpy(&cell->index_buffer, ib, sizeof(cell->index_buffer));
+ else
+ memset(&cell->index_buffer, 0, sizeof(cell->index_buffer));
+
+ /* TODO make this more like a state */
+}
+
+
void
cell_init_vertex_functions(struct cell_context *cell)
{
cell->pipe.set_vertex_buffers = cell_set_vertex_buffers;
+ cell->pipe.set_index_buffer = cell_set_index_buffer;
cell->pipe.create_vertex_elements_state = cell_create_vertex_elements_state;
cell->pipe.bind_vertex_elements_state = cell_bind_vertex_elements_state;
cell->pipe.delete_vertex_elements_state = cell_delete_vertex_elements_state;
diff --git a/src/gallium/drivers/failover/fo_context.c b/src/gallium/drivers/failover/fo_context.c
index 9c9c1bdc45..761a0fce72 100644
--- a/src/gallium/drivers/failover/fo_context.c
+++ b/src/gallium/drivers/failover/fo_context.c
@@ -50,13 +50,8 @@ void failover_fail_over( struct failover_context *failover )
}
-static void failover_draw_elements( struct pipe_context *pipe,
- struct pipe_resource *indexResource,
- unsigned indexSize,
- int indexBias,
- unsigned prim,
- unsigned start,
- unsigned count)
+static void failover_draw_vbo( struct pipe_context *pipe,
+ const struct pipe_draw_info *info)
{
struct failover_context *failover = failover_context( pipe );
@@ -70,13 +65,7 @@ static void failover_draw_elements( struct pipe_context *pipe,
/* Try hardware:
*/
if (failover->mode == FO_HW) {
- failover->hw->draw_elements( failover->hw,
- indexResource,
- indexSize,
- indexBias,
- prim,
- start,
- count );
+ failover->hw->draw_vbo( failover->hw, info );
}
/* Possibly try software:
@@ -88,13 +77,7 @@ static void failover_draw_elements( struct pipe_context *pipe,
failover_state_emit( failover );
}
- failover->sw->draw_elements( failover->sw,
- indexResource,
- indexSize,
- indexBias,
- prim,
- start,
- count );
+ failover->sw->draw_vbo( failover->sw, info );
/* Be ready to switch back to hardware rendering without an
* intervening flush. Unlikely to be much performance impact to
@@ -104,13 +87,6 @@ static void failover_draw_elements( struct pipe_context *pipe,
}
}
-
-static void failover_draw_arrays( struct pipe_context *pipe,
- unsigned prim, unsigned start, unsigned count)
-{
- failover_draw_elements(pipe, NULL, 0, 0, prim, start, count);
-}
-
static unsigned int
failover_is_resource_referenced( struct pipe_context *_pipe,
struct pipe_resource *resource,
@@ -143,8 +119,7 @@ struct pipe_context *failover_create( struct pipe_context *hw,
failover->pipe.get_paramf = hw->get_paramf;
#endif
- failover->pipe.draw_arrays = failover_draw_arrays;
- failover->pipe.draw_elements = failover_draw_elements;
+ failover->pipe.draw_vbo = failover_draw_vbo;
failover->pipe.clear = hw->clear;
failover->pipe.clear_render_target = hw->clear_render_target;
failover->pipe.clear_depth_stencil = hw->clear_depth_stencil;
diff --git a/src/gallium/drivers/failover/fo_context.h b/src/gallium/drivers/failover/fo_context.h
index 9d3e0d0dba..1afa6c9cee 100644
--- a/src/gallium/drivers/failover/fo_context.h
+++ b/src/gallium/drivers/failover/fo_context.h
@@ -56,6 +56,7 @@
#define FO_NEW_VERTEX_BUFFER 0x40000
#define FO_NEW_VERTEX_ELEMENT 0x80000
#define FO_NEW_SAMPLE_MASK 0x100000
+#define FO_NEW_INDEX_BUFFER 0x200000
@@ -97,6 +98,7 @@ struct failover_context {
struct pipe_scissor_state scissor;
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
+ struct pipe_index_buffer index_buffer;
uint num_vertex_buffers;
diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c
index 12e42379f9..c265f381b6 100644
--- a/src/gallium/drivers/failover/fo_state.c
+++ b/src/gallium/drivers/failover/fo_state.c
@@ -583,6 +583,23 @@ failover_set_vertex_buffers(struct pipe_context *pipe,
}
+static void
+failover_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ if (ib)
+ memcpy(&failover->index_buffer, ib, sizeof(failover->index_buffer));
+ else
+ memset(&failover->index_buffer, 0, sizeof(failover->index_buffer));
+
+ failover->dirty |= FO_NEW_INDEX_BUFFER;
+ failover->sw->set_index_buffer( failover->sw, ib );
+ failover->hw->set_index_buffer( failover->hw, ib );
+}
+
+
void
failover_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
@@ -635,6 +652,7 @@ failover_init_state_functions( struct failover_context *failover )
failover->pipe.set_vertex_sampler_views = failover_set_vertex_sampler_views;
failover->pipe.set_viewport_state = failover_set_viewport_state;
failover->pipe.set_vertex_buffers = failover_set_vertex_buffers;
+ failover->pipe.set_index_buffer = failover_set_index_buffer;
failover->pipe.set_constant_buffer = failover_set_constant_buffer;
failover->pipe.create_sampler_view = failover_create_sampler_view;
failover->pipe.sampler_view_destroy = failover_sampler_view_destroy;
diff --git a/src/gallium/drivers/failover/fo_state_emit.c b/src/gallium/drivers/failover/fo_state_emit.c
index 147f23269c..7f434ff9d6 100644
--- a/src/gallium/drivers/failover/fo_state_emit.c
+++ b/src/gallium/drivers/failover/fo_state_emit.c
@@ -135,5 +135,10 @@ failover_state_emit( struct failover_context *failover )
failover->vertex_buffers );
}
+ if (failover->dirty & FO_NEW_INDEX_BUFFER) {
+ failover->sw->set_index_buffer( failover->sw,
+ &failover->index_buffer );
+ }
+
failover->dirty = 0;
}
diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c
index ab6f17b3ab..fe14a287ef 100644
--- a/src/gallium/drivers/galahad/glhd_context.c
+++ b/src/gallium/drivers/galahad/glhd_context.c
@@ -48,68 +48,13 @@ galahad_destroy(struct pipe_context *_pipe)
}
static void
-galahad_draw_arrays(struct pipe_context *_pipe,
- unsigned prim,
- unsigned start,
- unsigned count)
+galahad_draw_vbo(struct pipe_context *_pipe,
+ const struct pipe_draw_info *info)
{
struct galahad_context *glhd_pipe = galahad_context(_pipe);
struct pipe_context *pipe = glhd_pipe->pipe;
- pipe->draw_arrays(pipe,
- prim,
- start,
- count);
-}
-
-static void
-galahad_draw_elements(struct pipe_context *_pipe,
- struct pipe_resource *_indexResource,
- unsigned indexSize,
- int indexBias,
- unsigned prim,
- unsigned start,
- unsigned count)
-{
- struct galahad_context *glhd_pipe = galahad_context(_pipe);
- struct galahad_resource *glhd_resource = galahad_resource(_indexResource);
- struct pipe_context *pipe = glhd_pipe->pipe;
- struct pipe_resource *indexResource = glhd_resource->resource;
-
- pipe->draw_elements(pipe,
- indexResource,
- indexSize,
- indexBias,
- prim,
- start,
- count);
-}
-
-static void
-galahad_draw_range_elements(struct pipe_context *_pipe,
- struct pipe_resource *_indexResource,
- unsigned indexSize,
- int indexBias,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count)
-{
- struct galahad_context *glhd_pipe = galahad_context(_pipe);
- struct galahad_resource *glhd_resource = galahad_resource(_indexResource);
- struct pipe_context *pipe = glhd_pipe->pipe;
- struct pipe_resource *indexResource = glhd_resource->resource;
-
- pipe->draw_range_elements(pipe,
- indexResource,
- indexSize,
- indexBias,
- minIndex,
- maxIndex,
- mode,
- start,
- count);
+ pipe->draw_vbo(pipe, info);
}
static struct pipe_query *
@@ -650,6 +595,41 @@ galahad_set_vertex_buffers(struct pipe_context *_pipe,
num_buffers,
buffers);
}
+
+static void
+galahad_set_index_buffer(struct pipe_context *_pipe,
+ const struct pipe_index_buffer *_ib)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_index_buffer unwrapped_ib, *ib = NULL;
+
+ if (_ib->buffer) {
+ switch (_ib->index_size) {
+ case 1:
+ case 2:
+ case 4:
+ break;
+ default:
+ glhd_warn("index buffer %p has unrecognized index size %d",
+ _ib->buffer, _ib->index_size);
+ break;
+ }
+ }
+ else if (_ib->offset || _ib->index_size) {
+ glhd_warn("non-indexed state with index offset %d and index size %d",
+ _ib->offset, _ib->index_size);
+ }
+
+ if (_ib) {
+ unwrapped_ib = *_ib;
+ unwrapped_ib.buffer = galahad_resource_unwrap(_ib->buffer);
+ ib = &unwrapped_ib;
+ }
+
+ pipe->set_index_buffer(pipe, ib);
+}
+
static void
galahad_resource_copy_region(struct pipe_context *_pipe,
struct pipe_resource *_dst,
@@ -934,9 +914,7 @@ galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
glhd_pipe->base.draw = NULL;
glhd_pipe->base.destroy = galahad_destroy;
- glhd_pipe->base.draw_arrays = galahad_draw_arrays;
- glhd_pipe->base.draw_elements = galahad_draw_elements;
- glhd_pipe->base.draw_range_elements = galahad_draw_range_elements;
+ glhd_pipe->base.draw_vbo = galahad_draw_vbo;
glhd_pipe->base.create_query = galahad_create_query;
glhd_pipe->base.destroy_query = galahad_destroy_query;
glhd_pipe->base.begin_query = galahad_begin_query;
@@ -976,6 +954,7 @@ galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
glhd_pipe->base.set_fragment_sampler_views = galahad_set_fragment_sampler_views;
glhd_pipe->base.set_vertex_sampler_views = galahad_set_vertex_sampler_views;
glhd_pipe->base.set_vertex_buffers = galahad_set_vertex_buffers;
+ glhd_pipe->base.set_index_buffer = galahad_set_index_buffer;
glhd_pipe->base.resource_copy_region = galahad_resource_copy_region;
glhd_pipe->base.clear = galahad_clear;
glhd_pipe->base.clear_render_target = galahad_clear_render_target;
diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c
index 2af9bdac95..2beb9e3091 100644
--- a/src/gallium/drivers/i915/i915_context.c
+++ b/src/gallium/drivers/i915/i915_context.c
@@ -45,16 +45,11 @@
static void
-i915_draw_range_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned min_index,
- unsigned max_index,
- unsigned prim, unsigned start, unsigned count)
+i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct i915_context *i915 = i915_context(pipe);
struct draw_context *draw = i915->draw;
+ void *mapped_indices = NULL;
unsigned i;
if (i915->dirty)
@@ -71,16 +66,18 @@ i915_draw_range_elements(struct pipe_context *pipe,
/*
* Map index buffer, if present
*/
- if (indexBuffer) {
- void *mapped_indexes = i915_buffer(indexBuffer)->data;
- draw_set_mapped_element_buffer_range(draw, indexSize, indexBias,
- min_index,
- max_index,
- mapped_indexes);
- } else {
- draw_set_mapped_element_buffer(draw, 0, 0, NULL);
+ if (info->indexed && i915->index_buffer.buffer) {
+ char *indices = (char *) i915_buffer(i915->index_buffer.buffer)->data;
+ mapped_indices = (void *) (indices + i915->index_buffer.offset);
}
+ draw_set_mapped_element_buffer_range(draw, (mapped_indices) ?
+ i915->index_buffer.index_size : 0,
+ info->index_bias,
+ info->min_index,
+ info->max_index,
+ mapped_indices);
+
draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0,
i915->current.constants[PIPE_SHADER_VERTEX],
@@ -90,7 +87,7 @@ i915_draw_range_elements(struct pipe_context *pipe,
/*
* Do the drawing
*/
- draw_arrays(i915->draw, prim, start, count);
+ draw_arrays(i915->draw, info->mode, info->start, info->count);
/*
* unmap vertex/index buffers
@@ -99,32 +96,11 @@ i915_draw_range_elements(struct pipe_context *pipe,
draw_set_mapped_vertex_buffer(draw, i, NULL);
}
- if (indexBuffer) {
+ if (mapped_indices) {
draw_set_mapped_element_buffer(draw, 0, 0, NULL);
}
}
-static void
-i915_draw_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned prim, unsigned start, unsigned count)
-{
- i915_draw_range_elements(pipe, indexBuffer,
- indexSize, indexBias,
- 0, 0xffffffff,
- prim, start, count);
-}
-
-static void
-i915_draw_arrays(struct pipe_context *pipe,
- unsigned prim, unsigned start, unsigned count)
-{
- i915_draw_elements(pipe, NULL, 0, 0, prim, start, count);
-}
-
-
-
/*
* Generic context functions
@@ -168,9 +144,7 @@ i915_create_context(struct pipe_screen *screen, void *priv)
i915->base.clear = i915_clear;
- i915->base.draw_arrays = i915_draw_arrays;
- i915->base.draw_elements = i915_draw_elements;
- i915->base.draw_range_elements = i915_draw_range_elements;
+ i915->base.draw_vbo = i915_draw_vbo;
/*
* Create drawing context and plug our rendering stage into it.
diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h
index b210cb130d..3ae61d0ea7 100644
--- a/src/gallium/drivers/i915/i915_context.h
+++ b/src/gallium/drivers/i915/i915_context.h
@@ -221,6 +221,7 @@ struct i915_context
struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+ struct pipe_index_buffer index_buffer;
unsigned dirty;
diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c
index e767aa9f8f..385c3b2d2d 100644
--- a/src/gallium/drivers/i915/i915_state.c
+++ b/src/gallium/drivers/i915/i915_state.c
@@ -812,6 +812,19 @@ i915_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)
FREE( velems );
}
+static void i915_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct i915_context *i915 = i915_context(pipe);
+
+ if (ib)
+ memcpy(&i915->index_buffer, ib, sizeof(i915->index_buffer));
+ else
+ memset(&i915->index_buffer, 0, sizeof(i915->index_buffer));
+
+ /* TODO make this more like a state */
+}
+
static void
i915_set_sample_mask(struct pipe_context *pipe,
unsigned sample_mask)
@@ -860,4 +873,5 @@ i915_init_state_functions( struct i915_context *i915 )
i915->base.sampler_view_destroy = i915_sampler_view_destroy;
i915->base.set_viewport_state = i915_set_viewport_state;
i915->base.set_vertex_buffers = i915_set_vertex_buffers;
+ i915->base.set_index_buffer = i915_set_index_buffer;
}
diff --git a/src/gallium/drivers/i965/brw_context.h b/src/gallium/drivers/i965/brw_context.h
index 94c9c443f0..56d351f97d 100644
--- a/src/gallium/drivers/i965/brw_context.h
+++ b/src/gallium/drivers/i965/brw_context.h
@@ -576,6 +576,7 @@ struct brw_context
*/
struct pipe_resource *index_buffer;
unsigned index_size;
+ unsigned index_offset;
/* Updates are signalled by PIPE_NEW_INDEX_RANGE:
*/
diff --git a/src/gallium/drivers/i965/brw_draw.c b/src/gallium/drivers/i965/brw_draw.c
index 4625c2048f..3ab9024c31 100644
--- a/src/gallium/drivers/i965/brw_draw.c
+++ b/src/gallium/drivers/i965/brw_draw.c
@@ -142,7 +142,7 @@ static int brw_emit_prim(struct brw_context *brw,
*/
static int
try_draw_range_elements(struct brw_context *brw,
- struct pipe_resource *index_buffer,
+ boolean indexed,
unsigned hw_prim,
unsigned start, unsigned count)
{
@@ -165,7 +165,7 @@ try_draw_range_elements(struct brw_context *brw,
if (ret)
return ret;
- ret = brw_emit_prim(brw, start, count, index_buffer != NULL, hw_prim);
+ ret = brw_emit_prim(brw, start, count, indexed, hw_prim);
if (ret)
return ret;
@@ -177,91 +177,54 @@ try_draw_range_elements(struct brw_context *brw,
static void
-brw_draw_range_elements(struct pipe_context *pipe,
- struct pipe_resource *index_buffer,
- unsigned index_size, int index_bias,
- unsigned min_index,
- unsigned max_index,
- unsigned mode, unsigned start, unsigned count)
+brw_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct brw_context *brw = brw_context(pipe);
int ret;
uint32_t hw_prim;
- hw_prim = brw_set_prim(brw, mode);
+ hw_prim = brw_set_prim(brw, info->mode);
if (BRW_DEBUG & DEBUG_PRIMS)
debug_printf("PRIM: %s start %d count %d index_buffer %p\n",
- u_prim_name(mode), start, count, (void *)index_buffer);
+ u_prim_name(info->mode), info->start, info->count,
+ (void *) brw->curr.index_buffer);
- assert(index_bias == 0);
+ assert(info->index_bias == 0);
- /* Potentially trigger upload of new index buffer.
- *
- * XXX: do we need to go through state validation to achieve this?
- * Could just call upload code directly.
+ /* Potentially trigger upload of new index buffer range.
+ * XXX: do we really care?
*/
- if (brw->curr.index_buffer != index_buffer ||
- brw->curr.index_size != index_size) {
- pipe_resource_reference( &brw->curr.index_buffer, index_buffer );
- brw->curr.index_size = index_size;
- brw->state.dirty.mesa |= PIPE_NEW_INDEX_BUFFER;
- }
-
- /* XXX: do we really care?
- */
- if (brw->curr.min_index != min_index ||
- brw->curr.max_index != max_index)
+ if (brw->curr.min_index != info->min_index ||
+ brw->curr.max_index != info->max_index)
{
- brw->curr.min_index = min_index;
- brw->curr.max_index = max_index;
+ brw->curr.min_index = info->min_index;
+ brw->curr.max_index = info->max_index;
brw->state.dirty.mesa |= PIPE_NEW_INDEX_RANGE;
}
/* Make a first attempt at drawing:
*/
- ret = try_draw_range_elements(brw, index_buffer, hw_prim, start, count );
+ ret = try_draw_range_elements(brw, info->indexed,
+ hw_prim, info->start, info->count);
/* Otherwise, flush and retry:
*/
if (ret != 0) {
brw_context_flush( brw );
- ret = try_draw_range_elements(brw, index_buffer, hw_prim, start, count );
+ ret = try_draw_range_elements(brw, info->indexed,
+ hw_prim, info->start, info->count);
assert(ret == 0);
}
}
-static void
-brw_draw_elements(struct pipe_context *pipe,
- struct pipe_resource *index_buffer,
- unsigned index_size, int index_bias,
- unsigned mode,
- unsigned start, unsigned count)
-{
- brw_draw_range_elements( pipe, index_buffer,
- index_size, index_bias,
- 0, 0xffffffff,
- mode,
- start, count );
-}
-
-static void
-brw_draw_arrays(struct pipe_context *pipe, unsigned mode,
- unsigned start, unsigned count)
-{
- brw_draw_elements(pipe, NULL, 0, 0, mode, start, count);
-}
-
-
boolean brw_draw_init( struct brw_context *brw )
{
/* Register our drawing function:
*/
- brw->base.draw_arrays = brw_draw_arrays;
- brw->base.draw_elements = brw_draw_elements;
- brw->base.draw_range_elements = brw_draw_range_elements;
+ brw->base.draw_vbo = brw_draw_vbo;
/* Create helpers for uploading data in user buffers:
*/
diff --git a/src/gallium/drivers/i965/brw_draw_upload.c b/src/gallium/drivers/i965/brw_draw_upload.c
index 337eee8cd9..ebeb1e146a 100644
--- a/src/gallium/drivers/i965/brw_draw_upload.c
+++ b/src/gallium/drivers/i965/brw_draw_upload.c
@@ -231,7 +231,7 @@ static int brw_prepare_indices(struct brw_context *brw)
struct pipe_resource *upload_buf = NULL;
struct brw_winsys_buffer *bo = NULL;
GLuint offset;
- GLuint index_size;
+ GLuint index_size, index_offset;
GLuint ib_size;
int ret;
@@ -246,13 +246,14 @@ static int brw_prepare_indices(struct brw_context *brw)
ib_size = index_buffer->width0;
index_size = brw->curr.index_size;
+ index_offset = brw->curr.index_offset;
/* Turn userbuffer into a proper hardware buffer?
*/
if (brw_buffer_is_user_buffer(index_buffer)) {
ret = u_upload_buffer( brw->vb.upload_index,
- 0,
+ index_offset,
ib_size,
index_buffer,
&offset,
@@ -269,7 +270,7 @@ static int brw_prepare_indices(struct brw_context *brw)
else {
bo = brw_buffer(index_buffer)->bo;
ib_size = bo->size;
- offset = 0;
+ offset = index_offset;
}
/* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading the
diff --git a/src/gallium/drivers/i965/brw_pipe_vertex.c b/src/gallium/drivers/i965/brw_pipe_vertex.c
index 4a120a51da..007239efc4 100644
--- a/src/gallium/drivers/i965/brw_pipe_vertex.c
+++ b/src/gallium/drivers/i965/brw_pipe_vertex.c
@@ -274,10 +274,41 @@ static void brw_set_vertex_buffers(struct pipe_context *pipe,
}
+static void brw_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ if (ib) {
+ if (brw->curr.index_buffer == ib->buffer &&
+ brw->curr.index_offset == ib->offset &&
+ brw->curr.index_size == ib->index_size)
+ return;
+
+ pipe_resource_reference(&brw->curr.index_buffer, ib->buffer);
+ brw->curr.index_offset = ib->offset;
+ brw->curr.index_size = ib->index_size;
+ }
+ else {
+ if (!brw->curr.index_buffer &&
+ !brw->curr.index_offset &&
+ !brw->curr.index_size)
+ return;
+
+ pipe_resource_reference(&brw->curr.index_buffer, NULL);
+ brw->curr.index_offset = 0;
+ brw->curr.index_size = 0;
+ }
+
+ brw->state.dirty.mesa |= PIPE_NEW_INDEX_BUFFER;
+}
+
+
void
brw_pipe_vertex_init( struct brw_context *brw )
{
brw->base.set_vertex_buffers = brw_set_vertex_buffers;
+ brw->base.set_index_buffer = brw_set_index_buffer;
brw->base.create_vertex_elements_state = brw_create_vertex_elements_state;
brw->base.bind_vertex_elements_state = brw_bind_vertex_elements_state;
brw->base.delete_vertex_elements_state = brw_delete_vertex_elements_state;
diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c
index 67be895b38..de83c24905 100644
--- a/src/gallium/drivers/identity/id_context.c
+++ b/src/gallium/drivers/identity/id_context.c
@@ -46,68 +46,13 @@ identity_destroy(struct pipe_context *_pipe)
}
static void
-identity_draw_arrays(struct pipe_context *_pipe,
- unsigned prim,
- unsigned start,
- unsigned count)
+identity_draw_vbo(struct pipe_context *_pipe,
+ const struct pipe_draw_info *info)
{
struct identity_context *id_pipe = identity_context(_pipe);
struct pipe_context *pipe = id_pipe->pipe;
- pipe->draw_arrays(pipe,
- prim,
- start,
- count);
-}
-
-static void
-identity_draw_elements(struct pipe_context *_pipe,
- struct pipe_resource *_indexResource,
- unsigned indexSize,
- int indexBias,
- unsigned prim,
- unsigned start,
- unsigned count)
-{
- struct identity_context *id_pipe = identity_context(_pipe);
- struct identity_resource *id_resource = identity_resource(_indexResource);
- struct pipe_context *pipe = id_pipe->pipe;
- struct pipe_resource *indexResource = id_resource->resource;
-
- pipe->draw_elements(pipe,
- indexResource,
- indexSize,
- indexBias,
- prim,
- start,
- count);
-}
-
-static void
-identity_draw_range_elements(struct pipe_context *_pipe,
- struct pipe_resource *_indexResource,
- unsigned indexSize,
- int indexBias,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count)
-{
- struct identity_context *id_pipe = identity_context(_pipe);
- struct identity_resource *id_resource = identity_resource(_indexResource);
- struct pipe_context *pipe = id_pipe->pipe;
- struct pipe_resource *indexResource = id_resource->resource;
-
- pipe->draw_range_elements(pipe,
- indexResource,
- indexSize,
- indexBias,
- minIndex,
- maxIndex,
- mode,
- start,
- count);
+ pipe->draw_vbo(pipe, info);
}
static struct pipe_query *
@@ -611,6 +556,24 @@ identity_set_vertex_buffers(struct pipe_context *_pipe,
num_buffers,
buffers);
}
+
+static void
+identity_set_index_buffer(struct pipe_context *_pipe,
+ const struct pipe_index_buffer *_ib)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_index_buffer unwrapped_ib, *ib = NULL;
+
+ if (_ib) {
+ unwrapped_ib = *_ib;
+ unwrapped_ib.buffer = identity_resource_unwrap(_ib->buffer);
+ ib = &unwrapped_ib;
+ }
+
+ pipe->set_index_buffer(pipe, ib);
+}
+
static void
identity_resource_copy_region(struct pipe_context *_pipe,
struct pipe_resource *_dst,
@@ -889,9 +852,7 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
id_pipe->base.draw = NULL;
id_pipe->base.destroy = identity_destroy;
- id_pipe->base.draw_arrays = identity_draw_arrays;
- id_pipe->base.draw_elements = identity_draw_elements;
- id_pipe->base.draw_range_elements = identity_draw_range_elements;
+ id_pipe->base.draw_vbo = identity_draw_vbo;
id_pipe->base.create_query = identity_create_query;
id_pipe->base.destroy_query = identity_destroy_query;
id_pipe->base.begin_query = identity_begin_query;
@@ -931,6 +892,7 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
id_pipe->base.set_fragment_sampler_views = identity_set_fragment_sampler_views;
id_pipe->base.set_vertex_sampler_views = identity_set_vertex_sampler_views;
id_pipe->base.set_vertex_buffers = identity_set_vertex_buffers;
+ id_pipe->base.set_index_buffer = identity_set_index_buffer;
id_pipe->base.resource_copy_region = identity_resource_copy_region;
id_pipe->base.clear = identity_clear;
id_pipe->base.clear_render_target = identity_clear_render_target;
diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript
index fd6ba1561e..5583fca38e 100644
--- a/src/gallium/drivers/llvmpipe/SConscript
+++ b/src/gallium/drivers/llvmpipe/SConscript
@@ -1,3 +1,4 @@
+from sys import executable as python_cmd
import distutils.version
Import('*')
@@ -16,7 +17,7 @@ env.CodeGenerate(
target = 'lp_tile_soa.c',
script = 'lp_tile_soa.py',
source = ['#src/gallium/auxiliary/util/u_format.csv'],
- command = 'python $SCRIPT $SOURCE > $TARGET'
+ command = python_cmd + ' $SCRIPT $SOURCE > $TARGET'
)
# XXX: Our dependency scanner only finds depended modules in relative dirs.
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
index e05bbe5011..99a768afd8 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_depth.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
@@ -258,16 +258,16 @@ lp_build_stencil_op_single(struct lp_build_context *bld,
}
if (stencil->writemask != stencilMax) {
- /* compute res = (res & mask) | (stencilVals & ~mask) */
- LLVMValueRef mask = lp_build_const_int_vec(type, stencil->writemask);
- LLVMValueRef cmask = LLVMBuildNot(bld->builder, mask, "notWritemask");
- LLVMValueRef t1 = LLVMBuildAnd(bld->builder, res, mask, "t1");
- LLVMValueRef t2 = LLVMBuildAnd(bld->builder, stencilVals, cmask, "t2");
- res = LLVMBuildOr(bld->builder, t1, t2, "t1_or_t2");
+ /* mask &= stencil->writemask */
+ LLVMValueRef writemask = lp_build_const_int_vec(type, stencil->writemask);
+ mask = LLVMBuildAnd(bld->builder, mask, writemask, "");
+ /* res = (res & mask) | (stencilVals & ~mask) */
+ res = lp_build_select_bitwise(bld, writemask, res, stencilVals);
+ }
+ else {
+ /* res = mask ? res : stencilVals */
+ res = lp_build_select(bld, mask, res, stencilVals);
}
-
- /* only the update the vector elements enabled by 'mask' */
- res = lp_build_select(bld, mask, res, stencilVals);
return res;
}
@@ -662,9 +662,9 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder,
}
/* Mix the old and new Z buffer values.
- * z_dst[i] = zselectmask[i] ? z_src[i] : z_dst[i]
+ * z_dst[i] = (zselectmask[i] & z_src[i]) | (~zselectmask[i] & z_dst[i])
*/
- z_dst = lp_build_select(&bld, zselectmask, z_src, z_dst);
+ z_dst = lp_build_select_bitwise(&bld, zselectmask, z_src, z_dst);
}
if (stencil[0].enabled) {
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.c b/src/gallium/drivers/llvmpipe/lp_bld_interp.c
index 78744da500..2cf6f38c4b 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_interp.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.c
@@ -141,7 +141,7 @@ coeffs_init(struct lp_build_interp_soa_context *bld,
else {
dadx = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dadx_ptr, &index, 1, ""), "");
dady = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dady_ptr, &index, 1, ""), "");
- dadxy = LLVMBuildAdd(builder, dadx, dady, "");
+ dadxy = LLVMBuildFAdd(builder, dadx, dady, "");
attrib_name(dadx, attrib, chan, ".dadx");
attrib_name(dady, attrib, chan, ".dady");
attrib_name(dadxy, attrib, chan, ".dadxy");
@@ -177,7 +177,7 @@ coeffs_init(struct lp_build_interp_soa_context *bld,
* dadq2 = 2 * dq
*/
- dadq2 = LLVMBuildAdd(builder, dadq, dadq, "");
+ dadq2 = LLVMBuildFAdd(builder, dadq, dadq, "");
/*
* a = a0 + x * dadx + y * dady
@@ -193,12 +193,11 @@ coeffs_init(struct lp_build_interp_soa_context *bld,
a = a0;
if (interp != LP_INTERP_CONSTANT &&
interp != LP_INTERP_FACING) {
- a = LLVMBuildAdd(builder, a,
- LLVMBuildMul(builder, bld->x, dadx, ""),
- "");
- a = LLVMBuildAdd(builder, a,
- LLVMBuildMul(builder, bld->y, dady, ""),
- "");
+ LLVMValueRef tmp;
+ tmp = LLVMBuildFMul(builder, bld->x, dadx, "");
+ a = LLVMBuildFAdd(builder, a, tmp, "");
+ tmp = LLVMBuildFMul(builder, bld->y, dady, "");
+ a = LLVMBuildFAdd(builder, a, tmp, "");
}
}
@@ -212,7 +211,7 @@ coeffs_init(struct lp_build_interp_soa_context *bld,
* Compute the attrib values on the upper-left corner of each quad.
*/
- a = LLVMBuildAdd(builder, a, dadq2, "");
+ a = LLVMBuildFAdd(builder, a, dadq2, "");
/*
* a *= 1 / w
diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c
index 3db4f12ebb..7543bd7b2b 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.c
+++ b/src/gallium/drivers/llvmpipe/lp_context.c
@@ -46,6 +46,10 @@
#include "lp_query.h"
#include "lp_setup.h"
+
+DEBUG_GET_ONCE_BOOL_OPTION(lp_no_rast, "LP_NO_RAST", FALSE)
+
+
static void llvmpipe_destroy( struct pipe_context *pipe )
{
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
@@ -130,7 +134,7 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
/* FIXME: devise alternative to draw_texture_samplers */
- if (debug_get_bool_option( "LP_NO_RAST", FALSE ))
+ if (debug_get_option_lp_no_rast())
llvmpipe->no_rast = TRUE;
llvmpipe->setup = lp_setup_create( &llvmpipe->pipe,
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index b2643ab33c..50f9091c3c 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -77,6 +77,7 @@ struct llvmpipe_context {
struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+ struct pipe_index_buffer index_buffer;
struct {
struct llvmpipe_resource *buffer[PIPE_MAX_SO_BUFFERS];
int offset[PIPE_MAX_SO_BUFFERS];
diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
index 625d0c8a8c..e73b431cb4 100644
--- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
+++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
@@ -49,20 +49,11 @@
* the drawing to the 'draw' module.
*/
static void
-llvmpipe_draw_range_elements_instanced(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count,
- unsigned startInstance,
- unsigned instanceCount)
+llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct llvmpipe_context *lp = llvmpipe_context(pipe);
struct draw_context *draw = lp->draw;
+ void *mapped_indices = NULL;
unsigned i;
if (lp->dirty)
@@ -77,27 +68,25 @@ llvmpipe_draw_range_elements_instanced(struct pipe_context *pipe,
}
/* Map index buffer, if present */
- if (indexBuffer) {
- void *mapped_indexes = llvmpipe_resource_data(indexBuffer);
- draw_set_mapped_element_buffer_range(draw,
- indexSize,
- indexBias,
- minIndex,
- maxIndex,
- mapped_indexes);
- }
- else {
- /* no index/element buffer */
- draw_set_mapped_element_buffer_range(draw, 0, 0, start,
- start + count - 1, NULL);
+ if (info->indexed && lp->index_buffer.buffer) {
+ char *indices = (char *) llvmpipe_resource_data(lp->index_buffer.buffer);
+ mapped_indices = (void *) (indices + lp->index_buffer.offset);
}
+
+ draw_set_mapped_element_buffer_range(draw, (mapped_indices) ?
+ lp->index_buffer.index_size : 0,
+ info->index_bias,
+ info->min_index,
+ info->max_index,
+ mapped_indices);
+
llvmpipe_prepare_vertex_sampling(lp,
lp->num_vertex_sampler_views,
lp->vertex_sampler_views);
/* draw! */
- draw_arrays_instanced(draw, mode, start, count,
- startInstance, instanceCount);
+ draw_arrays_instanced(draw, info->mode, info->start, info->count,
+ info->start_instance, info->instance_count);
/*
* unmap vertex/index buffers
@@ -105,7 +94,7 @@ llvmpipe_draw_range_elements_instanced(struct pipe_context *pipe,
for (i = 0; i < lp->num_vertex_buffers; i++) {
draw_set_mapped_vertex_buffer(draw, i, NULL);
}
- if (indexBuffer) {
+ if (mapped_indices) {
draw_set_mapped_element_buffer(draw, 0, 0, NULL);
}
llvmpipe_cleanup_vertex_sampling(lp);
@@ -119,112 +108,8 @@ llvmpipe_draw_range_elements_instanced(struct pipe_context *pipe,
}
-static void
-llvmpipe_draw_arrays_instanced(struct pipe_context *pipe,
- unsigned mode,
- unsigned start,
- unsigned count,
- unsigned startInstance,
- unsigned instanceCount)
-{
- llvmpipe_draw_range_elements_instanced(pipe,
- NULL, /* no indexBuffer */
- 0, 0, /* indexSize, indexBias */
- 0, ~0, /* minIndex, maxIndex */
- mode,
- start,
- count,
- startInstance,
- instanceCount);
-}
-
-
-static void
-llvmpipe_draw_elements_instanced(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned mode,
- unsigned start,
- unsigned count,
- unsigned startInstance,
- unsigned instanceCount)
-{
- llvmpipe_draw_range_elements_instanced(pipe,
- indexBuffer,
- indexSize, indexBias,
- 0, ~0, /* minIndex, maxIndex */
- mode,
- start,
- count,
- startInstance,
- instanceCount);
-}
-
-
-static void
-llvmpipe_draw_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned mode,
- unsigned start,
- unsigned count)
-{
- llvmpipe_draw_range_elements_instanced(pipe,
- indexBuffer,
- indexSize, indexBias,
- 0, 0xffffffff, /* min, maxIndex */
- mode, start, count,
- 0, /* startInstance */
- 1); /* instanceCount */
-}
-
-
-static void
-llvmpipe_draw_range_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned min_index,
- unsigned max_index,
- unsigned mode,
- unsigned start,
- unsigned count)
-{
- llvmpipe_draw_range_elements_instanced(pipe,
- indexBuffer,
- indexSize, indexBias,
- min_index, max_index,
- mode, start, count,
- 0, /* startInstance */
- 1); /* instanceCount */
-}
-
-
-static void
-llvmpipe_draw_arrays(struct pipe_context *pipe,
- unsigned mode,
- unsigned start,
- unsigned count)
-{
- llvmpipe_draw_range_elements_instanced(pipe,
- NULL, /* indexBuffer */
- 0, /* indexSize */
- 0, /* indexBias */
- 0, ~0, /* min, maxIndex */
- mode, start, count,
- 0, /* startInstance */
- 1); /* instanceCount */
-}
-
-
void
llvmpipe_init_draw_funcs(struct llvmpipe_context *llvmpipe)
{
- llvmpipe->pipe.draw_arrays = llvmpipe_draw_arrays;
- llvmpipe->pipe.draw_elements = llvmpipe_draw_elements;
- llvmpipe->pipe.draw_range_elements = llvmpipe_draw_range_elements;
- llvmpipe->pipe.draw_arrays_instanced = llvmpipe_draw_arrays_instanced;
- llvmpipe->pipe.draw_elements_instanced = llvmpipe_draw_elements_instanced;
+ llvmpipe->pipe.draw_vbo = llvmpipe_draw_vbo;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 654f4ea48e..3215d0f652 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -43,6 +43,12 @@
#include "lp_scene.h"
+#ifdef DEBUG
+int jit_line = 0;
+const struct lp_rast_state *jit_state = NULL;
+#endif
+
+
/**
* Begin rasterizing a scene.
* Called once per scene by one thread.
@@ -368,14 +374,15 @@ lp_rast_store_linear_color( struct lp_rasterizer_task *task,
for (buf = 0; buf < rast->state.nr_cbufs; buf++) {
struct pipe_surface *cbuf = scene->fb.cbufs[buf];
- const unsigned face = cbuf->face, level = cbuf->level;
+ const unsigned face_slice = cbuf->face + cbuf->zslice;
+ const unsigned level = cbuf->level;
struct llvmpipe_resource *lpt = llvmpipe_resource(cbuf->texture);
if (!task->color_tiles[buf])
continue;
llvmpipe_unswizzle_cbuf_tile(lpt,
- face,
+ face_slice,
level,
task->x, task->y,
task->color_tiles[buf]);
@@ -418,6 +425,7 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task,
depth = lp_rast_get_depth_block_pointer(task, tile_x + x, tile_y + y);
/* run shader on 4x4 block */
+ BEGIN_JIT_CALL(state);
variant->jit_function[RAST_WHOLE]( &state->jit_context,
tile_x + x, tile_y + y,
inputs->facing,
@@ -428,6 +436,7 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task,
depth,
0xffff,
&task->vis_counter);
+ END_JIT_CALL();
}
}
}
@@ -497,6 +506,7 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
assert(lp_check_alignment(state->jit_context.blend_color, 16));
/* run shader on 4x4 block */
+ BEGIN_JIT_CALL(state);
variant->jit_function[RAST_EDGE_TEST](&state->jit_context,
x, y,
inputs->facing,
@@ -507,6 +517,7 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
depth,
mask,
&task->vis_counter);
+ END_JIT_CALL();
}
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index eaf2a6f334..44319a0ad6 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -104,9 +104,6 @@ struct lp_rast_plane {
int dcdx;
int dcdy;
-
- /* edge/step info for 3 edges and 4x4 block of pixels */
- const int *step;
};
/**
@@ -119,8 +116,6 @@ struct lp_rast_triangle {
/* inputs for the shader */
struct lp_rast_shader_inputs inputs;
- int step[3][16];
-
#ifdef DEBUG
float v[3][2];
#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index b4a48cfd02..fae7f6d3dc 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -40,6 +40,34 @@
#include "lp_limits.h"
+/* If we crash in a jitted function, we can examine jit_line and jit_state
+ * to get some info. This is not thread-safe, however.
+ */
+#ifdef DEBUG
+
+extern int jit_line;
+extern const struct lp_rast_state *jit_state;
+
+#define BEGIN_JIT_CALL(state) \
+ do { \
+ jit_line = __LINE__; \
+ jit_state = state; \
+ } while (0)
+
+#define END_JIT_CALL() \
+ do { \
+ jit_line = 0; \
+ jit_state = NULL; \
+ } while (0)
+
+#else
+
+#define BEGIN_JIT_CALL(X)
+#define END_JIT_CALL()
+
+#endif
+
+
struct lp_rasterizer;
@@ -249,6 +277,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task,
depth = lp_rast_get_depth_block_pointer(task, x, y);
/* run shader on 4x4 block */
+ BEGIN_JIT_CALL(state);
variant->jit_function[RAST_WHOLE]( &state->jit_context,
x, y,
inputs->facing,
@@ -259,6 +288,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task,
depth,
0xffff,
&task->vis_counter );
+ END_JIT_CALL();
}
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_tri.c b/src/gallium/drivers/llvmpipe/lp_rast_tri.c
index ebe9a8e92b..980c18c024 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast_tri.c
@@ -37,52 +37,6 @@
#include "lp_tile_soa.h"
-/**
- * Map an index in [0,15] to an x,y position, multiplied by 4.
- * This is used to get the position of each subtile in a 4x4
- * grid of edge step values.
- * Note: we can use some bit twiddling to compute these values instead
- * of using a look-up table, but there's no measurable performance
- * difference.
- */
-static const int pos_table4[16][2] = {
- { 0, 0 },
- { 4, 0 },
- { 0, 4 },
- { 4, 4 },
- { 8, 0 },
- { 12, 0 },
- { 8, 4 },
- { 12, 4 },
- { 0, 8 },
- { 4, 8 },
- { 0, 12 },
- { 4, 12 },
- { 8, 8 },
- { 12, 8 },
- { 8, 12 },
- { 12, 12 }
-};
-
-
-static const int pos_table16[16][2] = {
- { 0, 0 },
- { 16, 0 },
- { 0, 16 },
- { 16, 16 },
- { 32, 0 },
- { 48, 0 },
- { 32, 16 },
- { 48, 16 },
- { 0, 32 },
- { 16, 32 },
- { 0, 48 },
- { 16, 48 },
- { 32, 32 },
- { 48, 32 },
- { 32, 48 },
- { 48, 48 }
-};
/**
@@ -113,6 +67,68 @@ block_full_16(struct lp_rasterizer_task *task,
block_full_4(task, tri, x + ix, y + iy);
}
+
+static INLINE unsigned
+build_mask(int c, int dcdx, int dcdy)
+{
+ int mask = 0;
+
+ int c0 = c;
+ int c1 = c0 + dcdx;
+ int c2 = c1 + dcdx;
+ int c3 = c2 + dcdx;
+
+ mask |= ((c0 + 0 * dcdy) >> 31) & (1 << 0);
+ mask |= ((c0 + 1 * dcdy) >> 31) & (1 << 2);
+ mask |= ((c0 + 2 * dcdy) >> 31) & (1 << 8);
+ mask |= ((c0 + 3 * dcdy) >> 31) & (1 << 10);
+ mask |= ((c1 + 0 * dcdy) >> 31) & (1 << 1);
+ mask |= ((c1 + 1 * dcdy) >> 31) & (1 << 3);
+ mask |= ((c1 + 2 * dcdy) >> 31) & (1 << 9);
+ mask |= ((c1 + 3 * dcdy) >> 31) & (1 << 11);
+ mask |= ((c2 + 0 * dcdy) >> 31) & (1 << 4);
+ mask |= ((c2 + 1 * dcdy) >> 31) & (1 << 6);
+ mask |= ((c2 + 2 * dcdy) >> 31) & (1 << 12);
+ mask |= ((c2 + 3 * dcdy) >> 31) & (1 << 14);
+ mask |= ((c3 + 0 * dcdy) >> 31) & (1 << 5);
+ mask |= ((c3 + 1 * dcdy) >> 31) & (1 << 7);
+ mask |= ((c3 + 2 * dcdy) >> 31) & (1 << 13);
+ mask |= ((c3 + 3 * dcdy) >> 31) & (1 << 15);
+
+ return mask;
+}
+
+static INLINE unsigned
+build_mask_linear(int c, int dcdx, int dcdy)
+{
+ int mask = 0;
+
+ int c0 = c;
+ int c1 = c0 + dcdy;
+ int c2 = c1 + dcdy;
+ int c3 = c2 + dcdy;
+
+ mask |= ((c0 + 0 * dcdx) >> 31) & (1 << 0);
+ mask |= ((c0 + 1 * dcdx) >> 31) & (1 << 1);
+ mask |= ((c0 + 2 * dcdx) >> 31) & (1 << 2);
+ mask |= ((c0 + 3 * dcdx) >> 31) & (1 << 3);
+ mask |= ((c1 + 0 * dcdx) >> 31) & (1 << 4);
+ mask |= ((c1 + 1 * dcdx) >> 31) & (1 << 5);
+ mask |= ((c1 + 2 * dcdx) >> 31) & (1 << 6);
+ mask |= ((c1 + 3 * dcdx) >> 31) & (1 << 7);
+ mask |= ((c2 + 0 * dcdx) >> 31) & (1 << 8);
+ mask |= ((c2 + 1 * dcdx) >> 31) & (1 << 9);
+ mask |= ((c2 + 2 * dcdx) >> 31) & (1 << 10);
+ mask |= ((c2 + 3 * dcdx) >> 31) & (1 << 11);
+ mask |= ((c3 + 0 * dcdx) >> 31) & (1 << 12);
+ mask |= ((c3 + 1 * dcdx) >> 31) & (1 << 13);
+ mask |= ((c3 + 2 * dcdx) >> 31) & (1 << 14);
+ mask |= ((c3 + 3 * dcdx) >> 31) & (1 << 15);
+
+ return mask;
+}
+
+
#define TAG(x) x##_1
#define NR_PLANES 1
#include "lp_rast_tri_tmp.h"
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h b/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h
index a410c611a3..43f72d8ca8 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h
@@ -46,19 +46,13 @@ TAG(do_block_4)(struct lp_rasterizer_task *task,
int x, int y,
const int *c)
{
- unsigned mask = 0;
- int i;
+ unsigned mask = 0xffff;
+ int j;
- for (i = 0; i < 16; i++) {
- int any_negative = 0;
- int j;
-
- for (j = 0; j < NR_PLANES; j++)
- any_negative |= (c[j] - 1 + plane[j].step[i]);
-
- any_negative >>= 31;
-
- mask |= (~any_negative) & (1 << i);
+ for (j = 0; j < NR_PLANES; j++) {
+ mask &= ~build_mask(c[j] - 1,
+ -plane[j].dcdx,
+ plane[j].dcdy);
}
/* Now pass to the shader:
@@ -79,24 +73,19 @@ TAG(do_block_16)(struct lp_rasterizer_task *task,
const int *c)
{
unsigned outmask, inmask, partmask, partial_mask;
- unsigned i, j;
+ unsigned j;
outmask = 0; /* outside one or more trivial reject planes */
partmask = 0; /* outside one or more trivial accept planes */
for (j = 0; j < NR_PLANES; j++) {
- const int *step = plane[j].step;
- const int eo = plane[j].eo * 4;
- const int ei = plane[j].ei * 4;
- const int cox = c[j] + eo;
- const int cio = ei - 1 - eo;
-
- for (i = 0; i < 16; i++) {
- int out = cox + step[i] * 4;
- int part = out + cio;
- outmask |= (out >> 31) & (1 << i);
- partmask |= (part >> 31) & (1 << i);
- }
+ const int dcdx = -plane[j].dcdx * 4;
+ const int dcdy = plane[j].dcdy * 4;
+ const int cox = c[j] + plane[j].eo * 4;
+ const int cio = c[j] + plane[j].ei * 4 - 1;
+
+ outmask |= build_mask_linear(cox, dcdx, dcdy);
+ partmask |= build_mask_linear(cio, dcdx, dcdy);
}
if (outmask == 0xffff)
@@ -117,15 +106,19 @@ TAG(do_block_16)(struct lp_rasterizer_task *task,
*/
while (partial_mask) {
int i = ffs(partial_mask) - 1;
- int px = x + pos_table4[i][0];
- int py = y + pos_table4[i][1];
+ int ix = (i & 3) * 4;
+ int iy = (i >> 2) * 4;
+ int px = x + ix;
+ int py = y + iy;
int cx[NR_PLANES];
- for (j = 0; j < NR_PLANES; j++)
- cx[j] = c[j] + plane[j].step[i] * 4;
-
partial_mask &= ~(1 << i);
+ for (j = 0; j < NR_PLANES; j++)
+ cx[j] = (c[j]
+ - plane[j].dcdx * ix
+ + plane[j].dcdy * iy);
+
TAG(do_block_4)(task, tri, plane, px, py, cx);
}
@@ -133,8 +126,10 @@ TAG(do_block_16)(struct lp_rasterizer_task *task,
*/
while (inmask) {
int i = ffs(inmask) - 1;
- int px = x + pos_table4[i][0];
- int py = y + pos_table4[i][1];
+ int ix = (i & 3) * 4;
+ int iy = (i >> 2) * 4;
+ int px = x + ix;
+ int py = y + iy;
inmask &= ~(1 << i);
@@ -157,35 +152,28 @@ TAG(lp_rast_triangle)(struct lp_rasterizer_task *task,
struct lp_rast_plane plane[NR_PLANES];
int c[NR_PLANES];
unsigned outmask, inmask, partmask, partial_mask;
- unsigned i, j, nr_planes = 0;
+ unsigned j = 0;
+
+ outmask = 0; /* outside one or more trivial reject planes */
+ partmask = 0; /* outside one or more trivial accept planes */
while (plane_mask) {
int i = ffs(plane_mask) - 1;
- plane[nr_planes] = tri->plane[i];
+ plane[j] = tri->plane[i];
plane_mask &= ~(1 << i);
- nr_planes++;
- };
-
- assert(nr_planes == NR_PLANES);
- outmask = 0; /* outside one or more trivial reject planes */
- partmask = 0; /* outside one or more trivial accept planes */
+ c[j] = plane[j].c + plane[j].dcdy * y - plane[j].dcdx * x;
- for (j = 0; j < NR_PLANES; j++) {
- const int *step = plane[j].step;
- const int eo = plane[j].eo * 16;
- const int ei = plane[j].ei * 16;
- int cox, cio;
+ {
+ const int dcdx = -plane[j].dcdx * 16;
+ const int dcdy = plane[j].dcdy * 16;
+ const int cox = c[j] + plane[j].eo * 16;
+ const int cio = c[j] + plane[j].ei * 16 - 1;
- c[j] = plane[j].c + plane[j].dcdy * y - plane[j].dcdx * x;
- cox = c[j] + eo;
- cio = ei - 1 - eo;
-
- for (i = 0; i < 16; i++) {
- int out = cox + step[i] * 16;
- int part = out + cio;
- outmask |= (out >> 31) & (1 << i);
- partmask |= (part >> 31) & (1 << i);
+ outmask |= build_mask_linear(cox, dcdx, dcdy);
+ partmask |= build_mask_linear(cio, dcdx, dcdy);
}
+
+ j++;
}
if (outmask == 0xffff)
@@ -206,12 +194,16 @@ TAG(lp_rast_triangle)(struct lp_rasterizer_task *task,
*/
while (partial_mask) {
int i = ffs(partial_mask) - 1;
- int px = x + pos_table16[i][0];
- int py = y + pos_table16[i][1];
+ int ix = (i & 3) * 16;
+ int iy = (i >> 2) * 16;
+ int px = x + ix;
+ int py = y + iy;
int cx[NR_PLANES];
for (j = 0; j < NR_PLANES; j++)
- cx[j] = c[j] + plane[j].step[i] * 16;
+ cx[j] = (c[j]
+ - plane[j].dcdx * ix
+ + plane[j].dcdy * iy);
partial_mask &= ~(1 << i);
@@ -223,8 +215,10 @@ TAG(lp_rast_triangle)(struct lp_rasterizer_task *task,
*/
while (inmask) {
int i = ffs(inmask) - 1;
- int px = x + pos_table16[i][0];
- int py = y + pos_table16[i][1];
+ int ix = (i & 3) * 16;
+ int iy = (i >> 2) * 16;
+ int px = x + ix;
+ int py = y + iy;
inmask &= ~(1 << i);
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
index 7e432503c1..393533ebee 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
@@ -61,36 +61,6 @@ struct tri_info {
-static const int step_scissor_minx[16] = {
- 0, 1, 0, 1,
- 2, 3, 2, 3,
- 0, 1, 0, 1,
- 2, 3, 2, 3
-};
-
-static const int step_scissor_maxx[16] = {
- 0, -1, 0, -1,
- -2, -3, -2, -3,
- 0, -1, 0, -1,
- -2, -3, -2, -3
-};
-
-static const int step_scissor_miny[16] = {
- 0, 0, 1, 1,
- 0, 0, 1, 1,
- 2, 2, 3, 3,
- 2, 2, 3, 3
-};
-
-static const int step_scissor_maxy[16] = {
- 0, 0, -1, -1,
- 0, 0, -1, -1,
- -2, -2, -3, -3,
- -2, -2, -3, -3
-};
-
-
-
static INLINE int
subpixel_snap(float a)
@@ -260,13 +230,13 @@ static void setup_tri_coefficients( struct lp_setup_context *setup,
{
unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
unsigned slot;
+ unsigned i;
/* setup interpolation for all the remaining attributes:
*/
for (slot = 0; slot < setup->fs.nr_inputs; slot++) {
unsigned vert_attr = setup->fs.input[slot].src_index;
unsigned usage_mask = setup->fs.input[slot].usage_mask;
- unsigned i;
switch (setup->fs.input[slot].interp) {
case LP_INTERP_CONSTANT:
@@ -316,6 +286,34 @@ static void setup_tri_coefficients( struct lp_setup_context *setup,
/* The internal position input is in slot zero:
*/
setup_fragcoord_coef(tri, info, 0, fragcoord_usage_mask);
+
+ if (0) {
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ float a0 = tri->inputs.a0 [0][i];
+ float dadx = tri->inputs.dadx[0][i];
+ float dady = tri->inputs.dady[0][i];
+
+ debug_printf("POS.%c: a0 = %f, dadx = %f, dady = %f\n",
+ "xyzw"[i],
+ a0, dadx, dady);
+ }
+
+ for (slot = 0; slot < setup->fs.nr_inputs; slot++) {
+ unsigned usage_mask = setup->fs.input[slot].usage_mask;
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ if (usage_mask & (1 << i)) {
+ float a0 = tri->inputs.a0 [1 + slot][i];
+ float dadx = tri->inputs.dadx[1 + slot][i];
+ float dady = tri->inputs.dady[1 + slot][i];
+
+ debug_printf("IN[%u].%c: a0 = %f, dadx = %f, dady = %f\n",
+ slot,
+ "xyzw"[i],
+ a0, dadx, dady);
+ }
+ }
+ }
+ }
}
@@ -525,7 +523,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
info.dx20 = info.v2[0][0] - info.v0[0][0];
info.dy01 = info.v0[0][1] - info.v1[0][1];
info.dy20 = info.v2[0][1] - info.v0[0][1];
- info.oneoverarea = 1.0 / (info.dx01 * info.dy20 - info.dx20 * info.dy01);
+ info.oneoverarea = 1.0f / (info.dx01 * info.dy20 - info.dx20 * info.dy01);
info.frontfacing = frontfacing;
/* Setup parameter interpolants:
@@ -590,35 +588,6 @@ do_triangle_ccw(struct lp_setup_context *setup,
/* Calculate trivial accept offsets from the above.
*/
plane->ei = plane->dcdy - plane->dcdx - plane->eo;
-
- plane->step = tri->step[i];
-
- /* Fill in the inputs.step[][] arrays.
- * We've manually unrolled some loops here.
- */
-#define SETUP_STEP(j, x, y) \
- tri->step[i][j] = y * plane->dcdy - x * plane->dcdx
-
- SETUP_STEP(0, 0, 0);
- SETUP_STEP(1, 1, 0);
- SETUP_STEP(2, 0, 1);
- SETUP_STEP(3, 1, 1);
-
- SETUP_STEP(4, 2, 0);
- SETUP_STEP(5, 3, 0);
- SETUP_STEP(6, 2, 1);
- SETUP_STEP(7, 3, 1);
-
- SETUP_STEP(8, 0, 2);
- SETUP_STEP(9, 1, 2);
- SETUP_STEP(10, 0, 3);
- SETUP_STEP(11, 1, 3);
-
- SETUP_STEP(12, 2, 2);
- SETUP_STEP(13, 3, 2);
- SETUP_STEP(14, 2, 3);
- SETUP_STEP(15, 3, 3);
-#undef STEP
}
@@ -641,28 +610,24 @@ do_triangle_ccw(struct lp_setup_context *setup,
* these planes elsewhere.
*/
if (nr_planes == 7) {
- tri->plane[3].step = step_scissor_minx;
tri->plane[3].dcdx = -1;
tri->plane[3].dcdy = 0;
tri->plane[3].c = 1-minx;
tri->plane[3].ei = 0;
tri->plane[3].eo = 1;
- tri->plane[4].step = step_scissor_maxx;
tri->plane[4].dcdx = 1;
tri->plane[4].dcdy = 0;
tri->plane[4].c = maxx;
tri->plane[4].ei = -1;
tri->plane[4].eo = 0;
- tri->plane[5].step = step_scissor_miny;
tri->plane[5].dcdx = 0;
tri->plane[5].dcdy = 1;
tri->plane[5].c = 1-miny;
tri->plane[5].ei = 0;
tri->plane[5].eo = 1;
- tri->plane[6].step = step_scissor_maxy;
tri->plane[6].dcdx = 0;
tri->plane[6].dcdy = -1;
tri->plane[6].c = maxy;
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 5953d690a4..dbca49a2ef 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -75,6 +75,7 @@
#include "gallivm/lp_bld_type.h"
#include "gallivm/lp_bld_const.h"
#include "gallivm/lp_bld_conv.h"
+#include "gallivm/lp_bld_init.h"
#include "gallivm/lp_bld_intr.h"
#include "gallivm/lp_bld_logic.h"
#include "gallivm/lp_bld_tgsi.h"
@@ -676,6 +677,11 @@ generate_fragment(struct llvmpipe_context *lp,
color_ptr);
}
+#ifdef PIPE_ARCH_X86
+ /* Avoid corrupting the FPU stack on 32bit OSes. */
+ lp_build_intrinsic(builder, "llvm.x86.mmx.emms", LLVMVoidType(), NULL, 0);
+#endif
+
LLVMBuildRetVoid(builder);
LLVMDisposeBuilder(builder);
@@ -710,6 +716,7 @@ generate_fragment(struct llvmpipe_context *lp,
if (gallivm_debug & GALLIVM_DEBUG_ASM) {
lp_disassemble(f);
}
+ lp_func_delete_body(function);
}
}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c
index 113f13db01..d86e66b4fb 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_vertex.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c
@@ -89,6 +89,19 @@ llvmpipe_set_vertex_buffers(struct pipe_context *pipe,
}
+static void
+llvmpipe_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ if (ib)
+ memcpy(&llvmpipe->index_buffer, ib, sizeof(llvmpipe->index_buffer));
+ else
+ memset(&llvmpipe->index_buffer, 0, sizeof(llvmpipe->index_buffer));
+
+ /* TODO make this more like a state */
+}
void
llvmpipe_init_vertex_funcs(struct llvmpipe_context *llvmpipe)
@@ -98,4 +111,5 @@ llvmpipe_init_vertex_funcs(struct llvmpipe_context *llvmpipe)
llvmpipe->pipe.delete_vertex_elements_state = llvmpipe_delete_vertex_elements_state;
llvmpipe->pipe.set_vertex_buffers = llvmpipe_set_vertex_buffers;
+ llvmpipe->pipe.set_index_buffer = llvmpipe_set_index_buffer;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c
index 0c95555655..d0389f0cb0 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_blend.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c
@@ -37,6 +37,7 @@
*/
+#include "gallivm/lp_bld_init.h"
#include "gallivm/lp_bld_type.h"
#include "gallivm/lp_bld_debug.h"
#include "lp_bld_blend.h"
@@ -485,8 +486,7 @@ test_one(unsigned verbose,
{
LLVMModuleRef module = NULL;
LLVMValueRef func = NULL;
- LLVMExecutionEngineRef engine = NULL;
- LLVMModuleProviderRef provider = NULL;
+ LLVMExecutionEngineRef engine = lp_build_engine;
LLVMPassManagerRef pass = NULL;
char *error = NULL;
blend_test_ptr_t blend_test_ptr;
@@ -510,15 +510,6 @@ test_one(unsigned verbose,
}
LLVMDisposeMessage(error);
- provider = LLVMCreateModuleProviderForExistingModule(module);
- if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
- if(verbose < 1)
- dump_blend_type(stderr, blend, mode, type);
- fprintf(stderr, "%s\n", error);
- LLVMDisposeMessage(error);
- abort();
- }
-
#if 0
pass = LLVMCreatePassManager();
LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
@@ -735,7 +726,6 @@ test_one(unsigned verbose,
LLVMFreeMachineCodeForFunction(engine, func);
- LLVMDisposeExecutionEngine(engine);
if(pass)
LLVMDisposePassManager(pass);
diff --git a/src/gallium/drivers/llvmpipe/lp_test_conv.c b/src/gallium/drivers/llvmpipe/lp_test_conv.c
index cf41b40581..3ba42bf11a 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_conv.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_conv.c
@@ -35,6 +35,7 @@
#include "util/u_pointer.h"
+#include "gallivm/lp_bld_init.h"
#include "gallivm/lp_bld_type.h"
#include "gallivm/lp_bld_const.h"
#include "gallivm/lp_bld_conv.h"
@@ -152,8 +153,7 @@ test_one(unsigned verbose,
{
LLVMModuleRef module = NULL;
LLVMValueRef func = NULL;
- LLVMExecutionEngineRef engine = NULL;
- LLVMModuleProviderRef provider = NULL;
+ LLVMExecutionEngineRef engine = lp_build_engine;
LLVMPassManagerRef pass = NULL;
char *error = NULL;
conv_test_ptr_t conv_test_ptr;
@@ -203,15 +203,6 @@ test_one(unsigned verbose,
}
LLVMDisposeMessage(error);
- provider = LLVMCreateModuleProviderForExistingModule(module);
- if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
- if(verbose < 1)
- dump_conv_types(stderr, src_type, dst_type);
- fprintf(stderr, "%s\n", error);
- LLVMDisposeMessage(error);
- abort();
- }
-
#if 0
pass = LLVMCreatePassManager();
LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
@@ -351,7 +342,6 @@ test_one(unsigned verbose,
LLVMFreeMachineCodeForFunction(engine, func);
- LLVMDisposeExecutionEngine(engine);
if(pass)
LLVMDisposePassManager(pass);
diff --git a/src/gallium/drivers/llvmpipe/lp_test_printf.c b/src/gallium/drivers/llvmpipe/lp_test_printf.c
index 21df83f9d8..4653f30e39 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_printf.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_printf.c
@@ -31,6 +31,8 @@
#include "util/u_pointer.h"
#include "gallivm/lp_bld.h"
+#include "gallivm/lp_bld_init.h"
+#include "gallivm/lp_bld_assert.h"
#include "gallivm/lp_bld_printf.h"
#include <llvm-c/Analysis.h>
@@ -74,6 +76,10 @@ add_printf_test(LLVMModuleRef module)
lp_build_printf(builder, "hello, world\n");
lp_build_printf(builder, "print 5 6: %d %d\n", LLVMConstInt(LLVMInt32Type(), 5, 0),
LLVMConstInt(LLVMInt32Type(), 6, 0));
+
+ /* Also test lp_build_assert(). This should not fail. */
+ lp_build_assert(builder, LLVMConstInt(LLVMInt32Type(), 1, 0), "assert(1)");
+
LLVMBuildRetVoid(builder);
LLVMDisposeBuilder(builder);
return func;
@@ -107,11 +113,16 @@ test_printf(unsigned verbose, FILE *fp, const struct printf_test_case *testcase)
LLVMDisposeMessage(error);
provider = LLVMCreateModuleProviderForExistingModule(module);
+#if 0
if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
fprintf(stderr, "%s\n", error);
LLVMDisposeMessage(error);
abort();
}
+#else
+ (void) provider;
+ engine = lp_build_engine;
+#endif
#if 0
pass = LLVMCreatePassManager();
diff --git a/src/gallium/drivers/llvmpipe/lp_test_round.c b/src/gallium/drivers/llvmpipe/lp_test_round.c
index f571a81a4a..57b0ee5776 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_round.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_round.c
@@ -31,7 +31,7 @@
#include "util/u_pointer.h"
#include "gallivm/lp_bld.h"
-#include "gallivm/lp_bld_printf.h"
+#include "gallivm/lp_bld_init.h"
#include "gallivm/lp_bld_arit.h"
#include <llvm-c/Analysis.h>
@@ -121,8 +121,7 @@ test_round(unsigned verbose, FILE *fp)
{
LLVMModuleRef module = NULL;
LLVMValueRef test_round = NULL, test_trunc, test_floor, test_ceil;
- LLVMExecutionEngineRef engine = NULL;
- LLVMModuleProviderRef provider = NULL;
+ LLVMExecutionEngineRef engine = lp_build_engine;
LLVMPassManagerRef pass = NULL;
char *error = NULL;
test_round_t round_func, trunc_func, floor_func, ceil_func;
@@ -145,13 +144,6 @@ test_round(unsigned verbose, FILE *fp)
}
LLVMDisposeMessage(error);
- provider = LLVMCreateModuleProviderForExistingModule(module);
- if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
- fprintf(stderr, "%s\n", error);
- LLVMDisposeMessage(error);
- abort();
- }
-
#if 0
pass = LLVMCreatePassManager();
LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
diff --git a/src/gallium/drivers/llvmpipe/lp_test_sincos.c b/src/gallium/drivers/llvmpipe/lp_test_sincos.c
index 1366ecddcb..7ab357f162 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_sincos.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_sincos.c
@@ -30,8 +30,9 @@
#include <stdio.h>
#include "gallivm/lp_bld.h"
-#include "gallivm/lp_bld_printf.h"
+#include "gallivm/lp_bld_init.h"
#include "gallivm/lp_bld_arit.h"
+#include "util/u_pointer.h"
#include <llvm-c/Analysis.h>
#include <llvm-c/ExecutionEngine.h>
@@ -101,8 +102,7 @@ test_sincos(unsigned verbose, FILE *fp)
{
LLVMModuleRef module = NULL;
LLVMValueRef test_sin = NULL, test_cos = NULL;
- LLVMExecutionEngineRef engine = NULL;
- LLVMModuleProviderRef provider = NULL;
+ LLVMExecutionEngineRef engine = lp_build_engine;
LLVMPassManagerRef pass = NULL;
char *error = NULL;
test_sincos_t sin_func;
@@ -122,13 +122,6 @@ test_sincos(unsigned verbose, FILE *fp)
}
LLVMDisposeMessage(error);
- provider = LLVMCreateModuleProviderForExistingModule(module);
- if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
- fprintf(stderr, "%s\n", error);
- LLVMDisposeMessage(error);
- abort();
- }
-
#if 0
pass = LLVMCreatePassManager();
LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
@@ -144,8 +137,8 @@ test_sincos(unsigned verbose, FILE *fp)
(void)pass;
#endif
- sin_func = (test_sincos_t)LLVMGetPointerToGlobal(engine, test_sin);
- cos_func = (test_sincos_t)LLVMGetPointerToGlobal(engine, test_cos);
+ sin_func = (test_sincos_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_sin));
+ cos_func = (test_sincos_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_cos));
memset(unpacked, 0, sizeof unpacked);
@@ -162,7 +155,6 @@ test_sincos(unsigned verbose, FILE *fp)
LLVMFreeMachineCodeForFunction(engine, test_sin);
LLVMFreeMachineCodeForFunction(engine, test_cos);
- LLVMDisposeExecutionEngine(engine);
if(pass)
LLVMDisposePassManager(pass);
diff --git a/src/gallium/drivers/llvmpipe/lp_tile_soa.py b/src/gallium/drivers/llvmpipe/lp_tile_soa.py
index c71ec8066c..2ba39052ab 100644
--- a/src/gallium/drivers/llvmpipe/lp_tile_soa.py
+++ b/src/gallium/drivers/llvmpipe/lp_tile_soa.py
@@ -293,34 +293,7 @@ def generate_ssse3():
print '''
#if defined(PIPE_ARCH_SSE)
-
-#if defined(PIPE_ARCH_SSSE3)
-
-#include <tmmintrin.h>
-
-#else
-
-#include <emmintrin.h>
-
-/**
- * Describe _mm_shuffle_epi8() with gcc extended inline assembly, for cases
- * where -mssse3 is not supported/enabled.
- *
- * MSVC will never get in here as its intrinsics support do not rely on
- * compiler command line options.
- */
-static __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm_shuffle_epi8(__m128i a, __m128i mask)
-{
- __m128i result;
- __asm__("pshufb %1, %0"
- : "=x" (result)
- : "xm" (mask), "0" (a));
- return result;
-}
-
-#endif
-
+#include "util/u_sse.h"
static void
lp_tile_b8g8r8a8_unorm_swizzle_4ub_ssse3(uint8_t *dst,
diff --git a/src/gallium/drivers/nouveau/nouveau_stateobj.h b/src/gallium/drivers/nouveau/nouveau_stateobj.h
index f5c1c5ca2c..e920cf9f3b 100644
--- a/src/gallium/drivers/nouveau/nouveau_stateobj.h
+++ b/src/gallium/drivers/nouveau/nouveau_stateobj.h
@@ -151,9 +151,9 @@ so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr,
if (so->start_alloc <= so->cur_start) {
debug_printf("exceeding num_start size\n");
assert(0);
- } else
+ }
#endif /* DEBUG_NOUVEAU_STATEOBJ */
- start = so->start;
+ start = so->start;
#ifdef DEBUG_NOUVEAU_STATEOBJ
if (so->cur_start > 0 && start[so->cur_start - 1].size > so->cur) {
@@ -162,7 +162,6 @@ so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr,
}
#endif /* DEBUG_NOUVEAU_STATEOBJ */
- so->start = start;
start[so->cur_start].gr = gr;
start[so->cur_start].mthd = mthd;
start[so->cur_start].size = size;
@@ -193,11 +192,10 @@ so_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo,
if (so->reloc_alloc <= so->cur_reloc) {
debug_printf("exceeding num_reloc size\n");
assert(0);
- } else
+ }
#endif /* DEBUG_NOUVEAU_STATEOBJ */
- r = so->reloc;
+ r = so->reloc;
- so->reloc = r;
r[so->cur_reloc].bo = NULL;
nouveau_bo_ref(bo, &(r[so->cur_reloc].bo));
r[so->cur_reloc].gr = so->start[so->cur_start-1].gr;
diff --git a/src/gallium/drivers/nouveau/nouveau_util.h b/src/gallium/drivers/nouveau/nouveau_util.h
index a5e8537533..b165f7a611 100644
--- a/src/gallium/drivers/nouveau/nouveau_util.h
+++ b/src/gallium/drivers/nouveau/nouveau_util.h
@@ -88,104 +88,4 @@ static INLINE unsigned log2i(unsigned i)
return r;
}
-struct u_split_prim {
- void *priv;
- void (*emit)(void *priv, unsigned start, unsigned count);
- void (*edge)(void *priv, boolean enabled);
-
- unsigned mode;
- unsigned start;
- unsigned p_start;
- unsigned p_end;
-
- uint repeat_first:1;
- uint close_first:1;
- uint edgeflag_off:1;
-};
-
-static INLINE void
-u_split_prim_init(struct u_split_prim *s,
- unsigned mode, unsigned start, unsigned count)
-{
- if (mode == PIPE_PRIM_LINE_LOOP) {
- s->mode = PIPE_PRIM_LINE_STRIP;
- s->close_first = 1;
- } else {
- s->mode = mode;
- s->close_first = 0;
- }
- s->start = start;
- s->p_start = start;
- s->p_end = start + count;
- s->edgeflag_off = 0;
- s->repeat_first = 0;
-}
-
-static INLINE boolean
-u_split_prim_next(struct u_split_prim *s, unsigned max_verts)
-{
- int repeat = 0;
-
- if (s->repeat_first) {
- s->emit(s->priv, s->start, 1);
- max_verts--;
- if (s->edgeflag_off) {
- s->edge(s->priv, TRUE);
- s->edgeflag_off = FALSE;
- }
- }
-
- if (s->p_start + s->close_first + max_verts >= s->p_end) {
- s->emit(s->priv, s->p_start, s->p_end - s->p_start);
- if (s->close_first)
- s->emit(s->priv, s->start, 1);
- return TRUE;
- }
-
- switch (s->mode) {
- case PIPE_PRIM_LINES:
- max_verts &= ~1;
- break;
- case PIPE_PRIM_LINE_STRIP:
- repeat = 1;
- break;
- case PIPE_PRIM_POLYGON:
- max_verts--;
- s->emit(s->priv, s->p_start, max_verts);
- s->edge(s->priv, FALSE);
- s->emit(s->priv, s->p_start + max_verts, 1);
- s->p_start += max_verts;
- s->repeat_first = TRUE;
- s->edgeflag_off = TRUE;
- return FALSE;
- case PIPE_PRIM_TRIANGLES:
- max_verts = max_verts - (max_verts % 3);
- break;
- case PIPE_PRIM_TRIANGLE_STRIP:
- /* to ensure winding stays correct, always split
- * on an even number of generated triangles
- */
- max_verts = max_verts & ~1;
- repeat = 2;
- break;
- case PIPE_PRIM_TRIANGLE_FAN:
- s->repeat_first = TRUE;
- repeat = 1;
- break;
- case PIPE_PRIM_QUADS:
- max_verts &= ~3;
- break;
- case PIPE_PRIM_QUAD_STRIP:
- max_verts &= ~1;
- repeat = 2;
- break;
- default:
- break;
- }
-
- s->emit (s->priv, s->p_start, max_verts);
- s->p_start += (max_verts - repeat);
- return FALSE;
-}
-
#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h
index df79ca89ca..c6c93d40b8 100644
--- a/src/gallium/drivers/nouveau/nouveau_winsys.h
+++ b/src/gallium/drivers/nouveau/nouveau_winsys.h
@@ -24,11 +24,10 @@ nouveau_screen_transfer_flags(unsigned pipe)
flags |= NOUVEAU_BO_WR;
if (pipe & PIPE_TRANSFER_DISCARD)
flags |= NOUVEAU_BO_INVAL;
- if (pipe & PIPE_TRANSFER_DONTBLOCK)
- flags |= NOUVEAU_BO_NOWAIT;
- else
if (pipe & PIPE_TRANSFER_UNSYNCHRONIZED)
flags |= NOUVEAU_BO_NOSYNC;
+ else if (pipe & PIPE_TRANSFER_DONTBLOCK)
+ flags |= NOUVEAU_BO_NOWAIT;
return flags;
}
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c
index 915a925402..0874cb5e4e 100644
--- a/src/gallium/drivers/nv50/nv50_context.c
+++ b/src/gallium/drivers/nv50/nv50_context.c
@@ -82,10 +82,7 @@ nv50_create(struct pipe_screen *pscreen, void *priv)
nv50->pipe.destroy = nv50_destroy;
- nv50->pipe.draw_arrays = nv50_draw_arrays;
- nv50->pipe.draw_arrays_instanced = nv50_draw_arrays_instanced;
- nv50->pipe.draw_elements = nv50_draw_elements;
- nv50->pipe.draw_elements_instanced = nv50_draw_elements_instanced;
+ nv50->pipe.draw_vbo = nv50_draw_vbo;
nv50->pipe.clear = nv50_clear;
nv50->pipe.flush = nv50_flush;
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index 12c4a93a9b..d24d6c50ea 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -148,6 +148,7 @@ struct nv50_context {
struct pipe_resource *constbuf[PIPE_SHADER_TYPES];
struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
unsigned vtxbuf_nr;
+ struct pipe_index_buffer idxbuf;
struct nv50_vtxelt_stateobj *vtxelt;
struct nv50_sampler_stateobj *sampler[3][PIPE_MAX_SAMPLERS];
unsigned sampler_nr[3];
@@ -179,24 +180,8 @@ nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst,
extern struct draw_stage *nv50_draw_render_stage(struct nv50_context *nv50);
/* nv50_vbo.c */
-extern void nv50_draw_arrays(struct pipe_context *, unsigned mode,
- unsigned start, unsigned count);
-extern void nv50_draw_arrays_instanced(struct pipe_context *, unsigned mode,
- unsigned start, unsigned count,
- unsigned startInstance,
- unsigned instanceCount);
-extern void nv50_draw_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned mode, unsigned start,
- unsigned count);
-extern void nv50_draw_elements_instanced(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned mode, unsigned start,
- unsigned count,
- unsigned startInstance,
- unsigned instanceCount);
+extern void nv50_draw_vbo(struct pipe_context *pipe,
+ const struct pipe_draw_info *info);
extern void nv50_vtxelt_construct(struct nv50_vtxelt_stateobj *cso);
extern struct nouveau_stateobj *nv50_vbo_validate(struct nv50_context *nv50);
diff --git a/src/gallium/drivers/nv50/nv50_push.c b/src/gallium/drivers/nv50/nv50_push.c
index 481182dd8d..0091927a98 100644
--- a/src/gallium/drivers/nv50/nv50_push.c
+++ b/src/gallium/drivers/nv50/nv50_push.c
@@ -2,8 +2,8 @@
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
+#include "util/u_split_prim.h"
-#include "nouveau/nouveau_util.h"
#include "nv50_context.h"
#include "nv50_resource.h"
@@ -217,7 +217,7 @@ nv50_push_elements_instanced(struct pipe_context *pipe,
4; /* potential edgeflag enable/disable */
const unsigned v_overhead = 1 + /* VERTEX_DATA packet header */
2; /* potential edgeflag modification */
- struct u_split_prim s;
+ struct util_split_prim s;
unsigned vtx_size;
boolean nzi = FALSE;
int i;
@@ -335,7 +335,7 @@ nv50_push_elements_instanced(struct pipe_context *pipe,
ctx.attr[i].map = (uint8_t *)ctx.attr[i].map + ctx.attr[i].stride;
}
- u_split_prim_init(&s, mode, start, count);
+ util_split_prim_init(&s, mode, start, count);
do {
if (AVAIL_RING(chan) < p_overhead + (6 * vtx_size)) {
FIRE_RING(chan);
@@ -351,7 +351,7 @@ nv50_push_elements_instanced(struct pipe_context *pipe,
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
OUT_RING (chan, nv50_prim(s.mode) | (nzi ? (1 << 28) : 0));
- done = u_split_prim_next(&s, max_verts);
+ done = util_split_prim_next(&s, max_verts);
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
OUT_RING (chan, 0);
} while (!done);
diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c
index 88fee3630b..3afce06557 100644
--- a/src/gallium/drivers/nv50/nv50_state.c
+++ b/src/gallium/drivers/nv50/nv50_state.c
@@ -786,6 +786,20 @@ nv50_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
nv50->dirty |= NV50_NEW_ARRAYS;
}
+static void
+nv50_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ if (ib)
+ memcpy(&nv50->idxbuf, ib, sizeof(nv50->idxbuf));
+ else
+ memset(&nv50->idxbuf, 0, sizeof(nv50->idxbuf));
+
+ /* TODO make this more like a state */
+}
+
static void *
nv50_vtxelts_state_create(struct pipe_context *pipe,
unsigned num_elements,
@@ -871,5 +885,6 @@ nv50_init_state_functions(struct nv50_context *nv50)
nv50->pipe.bind_vertex_elements_state = nv50_vtxelts_state_bind;
nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers;
+ nv50->pipe.set_index_buffer = nv50_set_index_buffer;
}
diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c
index 4fe0df5683..d41a59d05d 100644
--- a/src/gallium/drivers/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nv50/nv50_vbo.c
@@ -24,8 +24,8 @@
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
+#include "util/u_split_prim.h"
-#include "nouveau/nouveau_util.h"
#include "nv50_context.h"
#include "nv50_resource.h"
@@ -83,7 +83,7 @@ instance_step(struct nv50_context *nv50, struct instance *a)
}
}
-void
+static void
nv50_draw_arrays_instanced(struct pipe_context *pipe,
unsigned mode, unsigned start, unsigned count,
unsigned startInstance, unsigned instanceCount)
@@ -130,13 +130,6 @@ nv50_draw_arrays_instanced(struct pipe_context *pipe,
}
}
-void
-nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
- unsigned count)
-{
- nv50_draw_arrays_instanced(pipe, mode, start, count, 0, 1);
-}
-
struct inline_ctx {
struct nv50_context *nv50;
void *map;
@@ -228,7 +221,7 @@ nv50_draw_elements_inline(struct pipe_context *pipe,
struct pipe_transfer *transfer;
struct instance a[16];
struct inline_ctx ctx;
- struct u_split_prim s;
+ struct util_split_prim s;
boolean nzi = FALSE;
unsigned overhead;
@@ -264,7 +257,7 @@ nv50_draw_elements_inline(struct pipe_context *pipe,
unsigned max_verts;
boolean done;
- u_split_prim_init(&s, mode, start, count);
+ util_split_prim_init(&s, mode, start, count);
do {
if (AVAIL_RING(chan) < (overhead + 6)) {
FIRE_RING(chan);
@@ -283,7 +276,7 @@ nv50_draw_elements_inline(struct pipe_context *pipe,
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
OUT_RING (chan, nv50_prim(s.mode) | (nzi ? (1<<28) : 0));
- done = u_split_prim_next(&s, max_verts);
+ done = util_split_prim_next(&s, max_verts);
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
OUT_RING (chan, 0);
} while (!done);
@@ -294,7 +287,7 @@ nv50_draw_elements_inline(struct pipe_context *pipe,
pipe_buffer_unmap(pipe, indexBuffer, transfer);
}
-void
+static void
nv50_draw_elements_instanced(struct pipe_context *pipe,
struct pipe_resource *indexBuffer,
unsigned indexSize, int indexBias,
@@ -374,13 +367,34 @@ nv50_draw_elements_instanced(struct pipe_context *pipe,
}
void
-nv50_draw_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned mode, unsigned start, unsigned count)
+nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
- nv50_draw_elements_instanced(pipe, indexBuffer, indexSize, indexBias,
- mode, start, count, 0, 1);
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ if (info->indexed && nv50->idxbuf.buffer) {
+ unsigned offset;
+
+ assert(nv50->idxbuf.offset % nv50->idxbuf.index_size == 0);
+ offset = nv50->idxbuf.offset / nv50->idxbuf.index_size;
+
+ nv50_draw_elements_instanced(pipe,
+ nv50->idxbuf.buffer,
+ nv50->idxbuf.index_size,
+ info->index_bias,
+ info->mode,
+ info->start + offset,
+ info->count,
+ info->start_instance,
+ info->instance_count);
+ }
+ else {
+ nv50_draw_arrays_instanced(pipe,
+ info->mode,
+ info->start,
+ info->count,
+ info->start_instance,
+ info->instance_count);
+ }
}
static INLINE boolean
diff --git a/src/gallium/drivers/nvfx/nvfx_context.c b/src/gallium/drivers/nvfx/nvfx_context.c
index 6d2dc4d5bf..7218abff22 100644
--- a/src/gallium/drivers/nvfx/nvfx_context.c
+++ b/src/gallium/drivers/nvfx/nvfx_context.c
@@ -55,8 +55,7 @@ nvfx_create(struct pipe_screen *pscreen, void *priv)
nvfx->pipe.screen = pscreen;
nvfx->pipe.priv = priv;
nvfx->pipe.destroy = nvfx_destroy;
- nvfx->pipe.draw_arrays = nvfx_draw_arrays;
- nvfx->pipe.draw_elements = nvfx_draw_elements;
+ nvfx->pipe.draw_vbo = nvfx_draw_vbo;
nvfx->pipe.clear = nvfx_clear;
nvfx->pipe.flush = nvfx_flush;
diff --git a/src/gallium/drivers/nvfx/nvfx_context.h b/src/gallium/drivers/nvfx/nvfx_context.h
index e48f9f3aa8..89f94c10bd 100644
--- a/src/gallium/drivers/nvfx/nvfx_context.h
+++ b/src/gallium/drivers/nvfx/nvfx_context.h
@@ -121,7 +121,8 @@ struct nvfx_context {
struct pipe_stencil_ref stencil_ref;
struct pipe_viewport_state viewport;
struct pipe_framebuffer_state framebuffer;
- struct pipe_resource *idxbuf;
+ struct pipe_index_buffer idxbuf;
+ struct pipe_resource *idxbuf_buffer;
unsigned idxbuf_format;
struct nvfx_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS];
@@ -235,13 +236,8 @@ extern void nvfx_init_transfer_functions(struct nvfx_context *nvfx);
/* nvfx_vbo.c */
extern boolean nvfx_vbo_validate(struct nvfx_context *nvfx);
extern void nvfx_vbo_relocate(struct nvfx_context *nvfx);
-extern void nvfx_draw_arrays(struct pipe_context *, unsigned mode,
- unsigned start, unsigned count);
-extern void nvfx_draw_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned mode, unsigned start,
- unsigned count);
+extern void nvfx_draw_vbo(struct pipe_context *pipe,
+ const struct pipe_draw_info *info);
/* nvfx_vertprog.c */
extern boolean nvfx_vertprog_validate(struct nvfx_context *nvfx);
diff --git a/src/gallium/drivers/nvfx/nvfx_fragprog.c b/src/gallium/drivers/nvfx/nvfx_fragprog.c
index 6772d9bd51..ee41f03b9b 100644
--- a/src/gallium/drivers/nvfx/nvfx_fragprog.c
+++ b/src/gallium/drivers/nvfx/nvfx_fragprog.c
@@ -842,7 +842,6 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
struct nouveau_channel* chan = nvfx->screen->base.channel;
struct nvfx_fragment_program *fp = nvfx->fragprog;
int update = 0;
- int i;
if (!fp->translated)
{
@@ -895,6 +894,7 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
{
struct nvfx_fragment_program_bo* fpbo = os_malloc_aligned(sizeof(struct nvfx_fragment_program) + fp->prog_size * fp->progs_per_bo, 16);
char *map, *buf;
+ int i;
if(fp->fpbo)
{
@@ -910,7 +910,7 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
map = fpbo->bo->map;
buf = fpbo->insn;
- for(int i = 0; i < fp->progs_per_bo; ++i)
+ for(i = 0; i < fp->progs_per_bo; ++i)
{
memcpy(buf, fp->insn, fp->insn_len * 4);
nvfx_fp_memcpy(map, fp->insn, fp->insn_len * 4);
@@ -931,6 +931,7 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
uint32_t* map = pipe_buffer_map(&nvfx->pipe, constbuf, PIPE_TRANSFER_READ, &transfer);
uint32_t* fpmap = (uint32_t*)((char*)fp->fpbo->bo->map + offset);
uint32_t* buf = (uint32_t*)((char*)fp->fpbo->insn + offset);
+ int i;
for (i = 0; i < fp->nr_consts; ++i) {
unsigned off = fp->consts[i].offset;
unsigned idx = fp->consts[i].index * 4;
diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c
index 80db28a07c..f2525ccb38 100644
--- a/src/gallium/drivers/nvfx/nvfx_screen.c
+++ b/src/gallium/drivers/nvfx/nvfx_screen.c
@@ -131,6 +131,8 @@ nvfx_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
return screen->is_nv4x ? 1 : 0;
case PIPE_CAP_GEOMETRY_SHADER4:
return 0;
+ case PIPE_CAP_DEPTH_CLAMP:
+ return 0; // TODO: implement depth clamp
default:
NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
return 0;
diff --git a/src/gallium/drivers/nvfx/nvfx_state.c b/src/gallium/drivers/nvfx/nvfx_state.c
index 30322d46d9..cd58e439d7 100644
--- a/src/gallium/drivers/nvfx/nvfx_state.c
+++ b/src/gallium/drivers/nvfx/nvfx_state.c
@@ -555,6 +555,20 @@ nvfx_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
}
+static void
+nvfx_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct nvfx_context *nvfx = nvfx_context(pipe);
+
+ if (ib)
+ memcpy(&nvfx->idxbuf, ib, sizeof(nvfx->idxbuf));
+ else
+ memset(&nvfx->idxbuf, 0, sizeof(nvfx->idxbuf));
+
+ /* TODO make this more like a state */
+}
+
static void *
nvfx_vtxelts_state_create(struct pipe_context *pipe,
unsigned num_elements,
@@ -635,4 +649,5 @@ nvfx_init_state_functions(struct nvfx_context *nvfx)
nvfx->pipe.bind_vertex_elements_state = nvfx_vtxelts_state_bind;
nvfx->pipe.set_vertex_buffers = nvfx_set_vertex_buffers;
+ nvfx->pipe.set_index_buffer = nvfx_set_index_buffer;
}
diff --git a/src/gallium/drivers/nvfx/nvfx_vbo.c b/src/gallium/drivers/nvfx/nvfx_vbo.c
index 520bae5aed..4aa3793842 100644
--- a/src/gallium/drivers/nvfx/nvfx_vbo.c
+++ b/src/gallium/drivers/nvfx/nvfx_vbo.c
@@ -85,7 +85,7 @@ nvfx_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_resource *ib,
unsigned type;
if (!ib) {
- nvfx->idxbuf = NULL;
+ nvfx->idxbuf_buffer = NULL;
nvfx->idxbuf_format = 0xdeadbeef;
return FALSE;
}
@@ -104,10 +104,10 @@ nvfx_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_resource *ib,
return FALSE;
}
- if (ib != nvfx->idxbuf ||
+ if (ib != nvfx->idxbuf_buffer ||
type != nvfx->idxbuf_format) {
nvfx->dirty |= NVFX_NEW_ARRAYS;
- nvfx->idxbuf = ib;
+ nvfx->idxbuf_buffer = ib;
nvfx->idxbuf_format = type;
}
@@ -158,7 +158,7 @@ nvfx_vbo_static_attrib(struct nvfx_context *nvfx,
pipe_buffer_unmap(&nvfx->pipe, vb->buffer, transfer);
}
-void
+static void
nvfx_draw_arrays(struct pipe_context *pipe,
unsigned mode, unsigned start, unsigned count)
{
@@ -463,7 +463,7 @@ nvfx_draw_elements_vbo(struct pipe_context *pipe,
}
}
-void
+static void
nvfx_draw_elements(struct pipe_context *pipe,
struct pipe_resource *indexBuffer,
unsigned indexSize, int indexBias,
@@ -491,11 +491,38 @@ nvfx_draw_elements(struct pipe_context *pipe,
pipe->flush(pipe, 0, NULL);
}
+void
+nvfx_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
+{
+ struct nvfx_context *nvfx = nvfx_context(pipe);
+
+ if (info->indexed && nvfx->idxbuf.buffer) {
+ unsigned offset;
+
+ assert(nvfx->idxbuf.offset % nvfx->idxbuf.index_size == 0);
+ offset = nvfx->idxbuf.offset / nvfx->idxbuf.index_size;
+
+ nvfx_draw_elements(pipe,
+ nvfx->idxbuf.buffer,
+ nvfx->idxbuf.index_size,
+ info->index_bias,
+ info->mode,
+ info->start + offset,
+ info->count);
+ }
+ else {
+ nvfx_draw_arrays(pipe,
+ info->mode,
+ info->start,
+ info->count);
+ }
+}
+
boolean
nvfx_vbo_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
- struct pipe_resource *ib = nvfx->idxbuf;
+ struct pipe_resource *ib = nvfx->idxbuf_buffer;
unsigned ib_format = nvfx->idxbuf_format;
int i;
int elements = MAX2(nvfx->vtxelt->num_elements, nvfx->hw_vtxelt_nr);
@@ -610,10 +637,10 @@ nvfx_vbo_relocate(struct nvfx_context *nvfx)
}
}
- if(nvfx->idxbuf)
+ if(nvfx->idxbuf_buffer)
{
unsigned ib_flags = nvfx->screen->index_buffer_reloc_flags | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY;
- struct nouveau_bo* bo = nvfx_resource(nvfx->idxbuf)->bo;
+ struct nouveau_bo* bo = nvfx_resource(nvfx->idxbuf_buffer)->bo;
assert(nvfx->screen->index_buffer_reloc_flags);
diff --git a/src/gallium/drivers/nvfx/nvfx_vertprog.c b/src/gallium/drivers/nvfx/nvfx_vertprog.c
index 80b98b62d3..24d9846310 100644
--- a/src/gallium/drivers/nvfx/nvfx_vertprog.c
+++ b/src/gallium/drivers/nvfx/nvfx_vertprog.c
@@ -299,7 +299,13 @@ nvfx_vp_arith(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, int slot, int op,
(3 << NVFX_VP(INST_COND_SWZ_W_SHIFT)));
if(!nvfx->is_nv4x) {
- hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT);
+ if(slot == 0)
+ hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT);
+ else
+ {
+ hw[0] |= ((op >> 4) << NV30_VP_INST_SCA_OPCODEH_SHIFT);
+ hw[1] |= ((op & 0xf) << NV30_VP_INST_SCA_OPCODEL_SHIFT);
+ }
// hw[3] |= NVFX_VP(INST_SCA_DEST_TEMP_MASK);
// hw[3] |= (mask << NVFX_VP(INST_VEC_WRITEMASK_SHIFT));
diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile
index 13152635a6..728bc40a5b 100644
--- a/src/gallium/drivers/r300/Makefile
+++ b/src/gallium/drivers/r300/Makefile
@@ -24,6 +24,7 @@ C_SOURCES = \
r300_vs.c \
r300_vs_draw.c \
r300_texture.c \
+ r300_texture_desc.c \
r300_tgsi_to_rc.c \
r300_transfer.c
diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript
index 552ed4e5be..bf023daaa5 100644
--- a/src/gallium/drivers/r300/SConscript
+++ b/src/gallium/drivers/r300/SConscript
@@ -34,6 +34,7 @@ r300 = env.ConvenienceLibrary(
'r300_vs.c',
'r300_vs_draw.c',
'r300_texture.c',
+ 'r300_texture_desc.c',
'r300_tgsi_to_rc.c',
'r300_transfer.c',
] + r300compiler) + r300compiler
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 895efaa1c4..47ffc0cb3c 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -21,7 +21,10 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "r300_context.h"
+#include "r300_emit.h"
+#include "r300_hyperz.h"
#include "r300_texture.h"
+#include "r300_winsys.h"
#include "util/u_format.h"
#include "util/u_pack_color.h"
@@ -81,7 +84,7 @@ static void r300_blitter_end(struct r300_context *r300)
}
static uint32_t r300_depth_clear_cb_value(enum pipe_format format,
- const float* rgba)
+ const float* rgba)
{
union util_color uc;
util_pack_color(rgba, format, &uc);
@@ -97,29 +100,29 @@ static boolean r300_cbzb_clear_allowed(struct r300_context *r300,
{
struct pipe_framebuffer_state *fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
- struct r300_surface *surf = r300_surface(fb->cbufs[0]);
- unsigned bpp;
/* Only color clear allowed, and only one colorbuffer. */
if (clear_buffers != PIPE_CLEAR_COLOR || fb->nr_cbufs != 1)
return FALSE;
- /* The colorbuffer must be point-sampled. */
- if (surf->base.texture->nr_samples > 1)
- return FALSE;
-
- bpp = util_format_get_blocksizebits(surf->base.format);
+ return r300_surface(fb->cbufs[0])->cbzb_allowed;
+}
- /* ZB can only work with the two pixel sizes. */
- if (bpp != 16 && bpp != 32)
- return FALSE;
+static uint32_t r300_depth_clear_value(enum pipe_format format,
+ double depth, unsigned stencil)
+{
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ return util_pack_z(format, depth);
- /* If the midpoint ZB offset is not aligned to 2048, it returns garbage
- * with certain texture sizes. Macrotiling ensures the alignment. */
- if (!r300_texture(surf->base.texture)->mip_macrotile[surf->base.level])
- return FALSE;
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+ return util_pack_z_stencil(format, depth, stencil);
- return TRUE;
+ default:
+ assert(0);
+ return 0;
+ }
}
/* Clear currently bound buffers. */
@@ -169,8 +172,27 @@ static void r300_clear(struct pipe_context* pipe,
(struct pipe_framebuffer_state*)r300->fb_state.state;
struct r300_hyperz_state *hyperz =
(struct r300_hyperz_state*)r300->hyperz_state.state;
+ struct r300_texture *zstex =
+ fb->zsbuf ? r300_texture(fb->zsbuf->texture) : NULL;
uint32_t width = fb->width;
uint32_t height = fb->height;
+ boolean has_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
+ uint32_t hyperz_dcv = hyperz->zb_depthclearvalue;
+
+ /* Enable fast Z clear.
+ * The zbuffer must be in micro-tiled mode, otherwise it locks up. */
+ if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && has_hyperz) {
+ hyperz_dcv = hyperz->zb_depthclearvalue =
+ r300_depth_clear_value(fb->zsbuf->format, depth, stencil);
+
+ r300_mark_fb_state_dirty(r300, R300_CHANGED_ZCLEAR_FLAG);
+ if (zstex->zmask_mem[fb->zsbuf->level]) {
+ r300->zmask_clear.dirty = TRUE;
+ buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
+ }
+ if (zstex->hiz_mem[fb->zsbuf->level])
+ r300->hiz_clear.dirty = TRUE;
+ }
/* Enable CBZB clear. */
if (r300_cbzb_clear_allowed(r300, buffers)) {
@@ -187,20 +209,61 @@ static void r300_clear(struct pipe_context* pipe,
}
/* Clear. */
- r300_blitter_begin(r300, R300_CLEAR);
- util_blitter_clear(r300->blitter,
- width,
- height,
- fb->nr_cbufs,
- buffers, rgba, depth, stencil);
- r300_blitter_end(r300);
+ if (buffers) {
+ /* Clear using the blitter. */
+ r300_blitter_begin(r300, R300_CLEAR);
+ util_blitter_clear(r300->blitter,
+ width,
+ height,
+ fb->nr_cbufs,
+ buffers, rgba, depth, stencil);
+ r300_blitter_end(r300);
+ } else if (r300->zmask_clear.dirty) {
+ /* Just clear zmask and hiz now, this does not use a standard draw
+ * procedure. */
+ unsigned dwords;
+
+ /* Calculate zmask_clear and hiz_clear atom sizes. */
+ r300_update_hyperz_state(r300);
+ dwords = r300->zmask_clear.size +
+ (r300->hiz_clear.dirty ? r300->hiz_clear.size : 0) +
+ r300_get_num_cs_end_dwords(r300);
+
+ /* Reserve CS space. */
+ if (dwords > (r300->cs->ndw - r300->cs->cdw)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ }
+
+ /* Emit clear packets. */
+ r300_emit_zmask_clear(r300, r300->zmask_clear.size,
+ r300->zmask_clear.state);
+ r300->zmask_clear.dirty = FALSE;
+ if (r300->hiz_clear.dirty) {
+ r300_emit_hiz_clear(r300, r300->hiz_clear.size,
+ r300->hiz_clear.state);
+ r300->hiz_clear.dirty = FALSE;
+ }
+ } else {
+ assert(0);
+ }
/* Disable CBZB clear. */
if (r300->cbzb_clear) {
r300->cbzb_clear = FALSE;
+ hyperz->zb_depthclearvalue = hyperz_dcv;
r300_mark_fb_state_dirty(r300, R300_CHANGED_CBZB_FLAG);
}
+ /* Enable fastfill and/or hiz.
+ *
+ * If we cleared zmask/hiz, it's in use now. The Hyper-Z state update
+ * looks if zmask/hiz is in use and enables fastfill accordingly. */
+ if (zstex &&
+ (zstex->zmask_in_use[fb->zsbuf->level] ||
+ zstex->hiz_in_use[fb->zsbuf->level])) {
+ r300->hyperz_state.dirty = TRUE;
+ }
+
/* XXX this flush "fixes" a hardlock in the cubestorm xscreensaver */
if (r300->flush_counter == 0)
pipe->flush(pipe, 0, NULL);
@@ -238,6 +301,33 @@ static void r300_clear_depth_stencil(struct pipe_context *pipe,
r300_blitter_end(r300);
}
+/* Flush a depth stencil buffer. */
+void r300_flush_depth_stencil(struct pipe_context *pipe,
+ struct pipe_resource *dst,
+ struct pipe_subresource subdst,
+ unsigned zslice)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct pipe_surface *dstsurf;
+ struct r300_texture *tex = r300_texture(dst);
+
+ if (!tex->zmask_mem[subdst.level])
+ return;
+ if (!tex->zmask_in_use[subdst.level])
+ return;
+
+ dstsurf = pipe->screen->get_tex_surface(pipe->screen, dst,
+ subdst.face, subdst.level, zslice,
+ PIPE_BIND_DEPTH_STENCIL);
+ r300->z_decomp_rd = TRUE;
+ r300_blitter_begin(r300, R300_CLEAR_SURFACE);
+ util_blitter_flush_depth_stencil(r300->blitter, dstsurf);
+ r300_blitter_end(r300);
+ r300->z_decomp_rd = FALSE;
+
+ tex->zmask_in_use[subdst.level] = FALSE;
+}
+
/* Copy a block of pixels from one surface to another using HW. */
static void r300_hw_copy_region(struct pipe_context* pipe,
struct pipe_resource *dst,
@@ -269,7 +359,7 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
{
enum pipe_format old_format = dst->format;
enum pipe_format new_format = old_format;
-
+ boolean is_depth;
if (!pipe->screen->is_format_supported(pipe->screen,
old_format, src->target,
src->nr_samples,
@@ -296,6 +386,10 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
}
}
+ is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
+ if (is_depth) {
+ r300_flush_depth_stencil(pipe, src, subsrc, srcz);
+ }
if (old_format != new_format) {
dst->format = new_format;
src->format = new_format;
diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c
index 21f3b9d261..48c2409211 100644
--- a/src/gallium/drivers/r300/r300_chipset.c
+++ b/src/gallium/drivers/r300/r300_chipset.c
@@ -36,7 +36,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->num_vert_fpus = 2;
caps->num_tex_units = 16;
caps->has_tcl = debug_get_bool_option("RADEON_NO_TCL", FALSE) ? FALSE : TRUE;
- caps->has_hiz = TRUE;
+ caps->hiz_ram = 0;
caps->is_r400 = FALSE;
caps->is_r500 = FALSE;
caps->high_second_pipe = FALSE;
@@ -49,6 +49,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_R300;
caps->high_second_pipe = TRUE;
caps->num_vert_fpus = 4;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x4145:
@@ -61,6 +63,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_R300;
caps->high_second_pipe = TRUE;
caps->num_vert_fpus = 4;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x4150:
@@ -77,8 +81,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x4E54:
case 0x4E56:
caps->family = CHIP_FAMILY_RV350;
- caps->has_hiz = FALSE;
caps->high_second_pipe = TRUE;
+ caps->zmask_ram = RV3xx_ZMASK_SIZE;
break;
case 0x4148:
@@ -91,12 +95,16 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_R350;
caps->high_second_pipe = TRUE;
caps->num_vert_fpus = 4;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x4E4A:
caps->family = CHIP_FAMILY_R360;
caps->high_second_pipe = TRUE;
caps->num_vert_fpus = 4;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x5460:
@@ -108,8 +116,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5B64:
case 0x5B65:
caps->family = CHIP_FAMILY_RV370;
- caps->has_hiz = FALSE;
caps->high_second_pipe = TRUE;
+ caps->zmask_ram = RV3xx_ZMASK_SIZE;
break;
case 0x3150:
@@ -120,6 +128,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x3E54:
caps->family = CHIP_FAMILY_RV380;
caps->high_second_pipe = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = RV3xx_ZMASK_SIZE;
break;
case 0x4A48:
@@ -135,6 +145,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_R420;
caps->num_vert_fpus = 6;
caps->is_r400 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x5548:
@@ -149,6 +161,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_R423;
caps->num_vert_fpus = 6;
caps->is_r400 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x554C:
@@ -161,6 +175,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_R430;
caps->num_vert_fpus = 6;
caps->is_r400 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x5D4C:
@@ -172,6 +188,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_R480;
caps->num_vert_fpus = 6;
caps->is_r400 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x4B48:
@@ -182,6 +200,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_R481;
caps->num_vert_fpus = 6;
caps->is_r400 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x5E4C:
@@ -199,34 +219,36 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_RV410;
caps->num_vert_fpus = 6;
caps->is_r400 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x5954:
case 0x5955:
caps->family = CHIP_FAMILY_RS480;
- caps->has_hiz = FALSE;
caps->has_tcl = FALSE;
+ caps->zmask_ram = RV3xx_ZMASK_SIZE;
break;
case 0x5974:
case 0x5975:
caps->family = CHIP_FAMILY_RS482;
- caps->has_hiz = FALSE;
caps->has_tcl = FALSE;
+ caps->zmask_ram = RV3xx_ZMASK_SIZE;
break;
case 0x5A41:
case 0x5A42:
caps->family = CHIP_FAMILY_RS400;
- caps->has_hiz = FALSE;
caps->has_tcl = FALSE;
+ caps->zmask_ram = RV3xx_ZMASK_SIZE;
break;
case 0x5A61:
case 0x5A62:
caps->family = CHIP_FAMILY_RC410;
- caps->has_hiz = FALSE;
caps->has_tcl = FALSE;
+ caps->zmask_ram = RV3xx_ZMASK_SIZE;
break;
case 0x791E:
@@ -234,6 +256,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_RS690;
caps->has_tcl = FALSE;
caps->is_r400 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x793F:
@@ -242,6 +266,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_RS600;
caps->has_tcl = FALSE;
caps->is_r400 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x796C:
@@ -251,6 +277,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_RS740;
caps->has_tcl = FALSE;
caps->is_r400 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x7100:
@@ -270,6 +298,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_R520;
caps->num_vert_fpus = 8;
caps->is_r500 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x7140:
@@ -313,6 +343,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_RV515;
caps->num_vert_fpus = 2;
caps->is_r500 = TRUE;
+ caps->hiz_ram = R300_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x71C0:
@@ -334,6 +366,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_RV530;
caps->num_vert_fpus = 5;
caps->is_r500 = TRUE;
+ /*caps->hiz_ram = RV530_HIZ_LIMIT;*/
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x7240:
@@ -354,12 +388,16 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_R580;
caps->num_vert_fpus = 8;
caps->is_r500 = TRUE;
+ caps->hiz_ram = RV530_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x7280:
caps->family = CHIP_FAMILY_RV570;
caps->num_vert_fpus = 8;
caps->is_r500 = TRUE;
+ caps->hiz_ram = RV530_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
case 0x7281:
@@ -376,6 +414,8 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->family = CHIP_FAMILY_RV560;
caps->num_vert_fpus = 8;
caps->is_r500 = TRUE;
+ caps->hiz_ram = RV530_HIZ_LIMIT;
+ caps->zmask_ram = PIPE_ZMASK_SIZE;
break;
default:
diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h
index 65750f54e7..e7ca642b4f 100644
--- a/src/gallium/drivers/r300/r300_chipset.h
+++ b/src/gallium/drivers/r300/r300_chipset.h
@@ -25,6 +25,14 @@
#include "pipe/p_compiler.h"
+/* these are sizes in dwords */
+#define R300_HIZ_LIMIT 10240
+#define RV530_HIZ_LIMIT 15360
+
+/* rv3xx have only one pipe */
+#define PIPE_ZMASK_SIZE 4096
+#define RV3xx_ZMASK_SIZE 5120
+
/* Structure containing all the possible information about a specific Radeon
* in the R3xx, R4xx, and R5xx families. */
struct r300_capabilities {
@@ -42,8 +50,10 @@ struct r300_capabilities {
unsigned num_tex_units;
/* Whether or not TCL is physically present */
boolean has_tcl;
- /* Some chipsets do not have HiZ RAM. */
- boolean has_hiz;
+ /* Some chipsets do not have HiZ RAM - other have varying amounts . */
+ int hiz_ram;
+ /* some chipsets have zmask ram per pipe some don't */
+ int zmask_ram;
/* Whether or not this is RV350 or newer, including all r400 and r500
* chipsets. The differences compared to the oldest r300 chips are:
* - Blend LTE/GTE thresholds
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index df90359058..e8b6c4f7af 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -30,6 +30,7 @@
#include "r300_cb.h"
#include "r300_context.h"
#include "r300_emit.h"
+#include "r300_hyperz.h"
#include "r300_screen.h"
#include "r300_screen_buffer.h"
#include "r300_winsys.h"
@@ -114,6 +115,10 @@ static void r300_destroy_context(struct pipe_context* context)
u_upload_destroy(r300->upload_vb);
u_upload_destroy(r300->upload_ib);
+ /* setup hyper-z mm */
+ if (r300->rws->get_value(r300->rws, R300_CAN_HYPERZ))
+ r300_hyperz_destroy_mm(r300);
+
translate_cache_destroy(r300->tran.translate_cache);
r300_release_referenced_objects(r300);
@@ -166,6 +171,9 @@ static void r300_setup_atoms(struct r300_context* r300)
boolean is_r500 = r300->screen->caps.is_r500;
boolean has_tcl = r300->screen->caps.has_tcl;
boolean drm_2_3_0 = r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0);
+ boolean drm_2_6_0 = r300->rws->get_value(r300->rws, R300_VID_DRM_2_6_0);
+ boolean has_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
+ boolean has_hiz_ram = r300->screen->caps.hiz_ram > 0;
/* Create the actual atom list.
*
@@ -188,8 +196,8 @@ static void r300_setup_atoms(struct r300_context* r300)
R300_INIT_ATOM(gpu_flush, 9);
R300_INIT_ATOM(aa_state, 4);
R300_INIT_ATOM(fb_state, 0);
+ R300_INIT_ATOM(hyperz_state, is_r500 || (is_rv350 && drm_2_6_0) ? 10 : 8);
/* ZB (unpipelined), SC. */
- R300_INIT_ATOM(hyperz_state, 6);
R300_INIT_ATOM(ztop_state, 2);
/* ZB, FG. */
R300_INIT_ATOM(dsa_state, is_r500 ? 8 : 6);
@@ -220,6 +228,13 @@ static void r300_setup_atoms(struct r300_context* r300)
/* TX. */
R300_INIT_ATOM(texture_cache_inval, 2);
R300_INIT_ATOM(textures_state, 0);
+ if (has_hyperz) {
+ /* HiZ Clear */
+ if (has_hiz_ram)
+ R300_INIT_ATOM(hiz_clear, 0);
+ /* zmask clear */
+ R300_INIT_ATOM(zmask_clear, 0);
+ }
/* ZB (unpipelined), SU. */
R300_INIT_ATOM(query_start, 4);
@@ -282,8 +297,7 @@ static void r300_init_states(struct pipe_context *pipe)
(struct r300_vap_invariant_state*)r300->vap_invariant_state.state;
struct r300_invariant_state *invariant =
(struct r300_invariant_state*)r300->invariant_state.state;
- struct r300_hyperz_state *hyperz =
- (struct r300_hyperz_state*)r300->hyperz_state.state;
+
CB_LOCALS;
pipe->set_blend_color(pipe, &bc);
@@ -351,10 +365,20 @@ static void r300_init_states(struct pipe_context *pipe)
/* Initialize the hyperz state. */
{
- BEGIN_CB(&hyperz->cb_begin, r300->hyperz_state.size);
+ struct r300_hyperz_state *hyperz =
+ (struct r300_hyperz_state*)r300->hyperz_state.state;
+ BEGIN_CB(&hyperz->cb_flush_begin, r300->hyperz_state.size);
+ OUT_CB_REG(R300_ZB_ZCACHE_CTLSTAT,
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE);
OUT_CB_REG(R300_ZB_BW_CNTL, 0);
OUT_CB_REG(R300_ZB_DEPTHCLEARVALUE, 0);
OUT_CB_REG(R300_SC_HYPERZ, R300_SC_HYPERZ_ADJ_2);
+
+ if (r300->screen->caps.is_r500 ||
+ (r300->screen->caps.is_rv350 &&
+ r300->rws->get_value(r300->rws, R300_VID_DRM_2_6_0))) {
+ OUT_CB_REG(R300_GB_Z_PEQ_CONFIG, 0);
+ }
END_CB;
}
}
@@ -415,6 +439,10 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
rws->cs_set_flush(r300->cs, r300_flush_cb, r300);
+ /* setup hyper-z mm */
+ if (r300->rws->get_value(r300->rws, R300_CAN_HYPERZ))
+ r300_hyperz_init_mm(r300);
+
r300->upload_ib = u_upload_create(&r300->context,
32 * 1024, 16,
PIPE_BIND_INDEX_BUFFER);
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index b9c96d5bdd..6fa7f470f9 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -106,13 +106,19 @@ struct r300_dsa_state {
};
struct r300_hyperz_state {
+ int current_func; /* -1 after a clear before first op */
+ int flush;
/* This is actually a command buffer with named dwords. */
+ uint32_t cb_flush_begin;
+ uint32_t zb_zcache_ctlstat; /* R300_ZB_CACHE_CNTL */
uint32_t cb_begin;
uint32_t zb_bw_cntl; /* R300_ZB_BW_CNTL */
uint32_t cb_reg1;
uint32_t zb_depthclearvalue; /* R300_ZB_DEPTHCLEARVALUE */
uint32_t cb_reg2;
uint32_t sc_hyperz; /* R300_SC_HYPERZ */
+ uint32_t cb_reg3;
+ uint32_t gb_z_peq_config; /* R300_GB_Z_PEQ_CONFIG: 0x4028 */
};
struct r300_gpu_flush {
@@ -318,29 +324,39 @@ struct r300_surface {
uint32_t cbzb_midpoint_offset; /* DEPTHOFFSET. */
uint32_t cbzb_pitch; /* DEPTHPITCH. */
uint32_t cbzb_format; /* ZB_FORMAT. */
+
+ /* Whether the CBZB clear is allowed on the surface. */
+ boolean cbzb_allowed;
+
};
-struct r300_texture {
- /* Parent class */
+struct r300_texture_desc {
+ /* Parent class. */
struct u_resource b;
- enum r300_buffer_domain domain;
+ /* Buffer tiling.
+ * Macrotiling is specified per-level because small mipmaps cannot
+ * be macrotiled. */
+ enum r300_buffer_tiling microtile;
+ enum r300_buffer_tiling macrotile[R300_MAX_TEXTURE_LEVELS];
/* Offsets into the buffer. */
- unsigned offset[R300_MAX_TEXTURE_LEVELS];
+ unsigned offset_in_bytes[R300_MAX_TEXTURE_LEVELS];
- /* A pitch for each mip-level */
- unsigned pitch[R300_MAX_TEXTURE_LEVELS];
+ /* Strides for each mip-level. */
+ unsigned stride_in_pixels[R300_MAX_TEXTURE_LEVELS];
+ unsigned stride_in_bytes[R300_MAX_TEXTURE_LEVELS];
- /* A pitch multiplied by blockwidth as hardware wants
- * the number of pixels instead of the number of blocks. */
- unsigned hwpitch[R300_MAX_TEXTURE_LEVELS];
+ /* Size of one zslice or face or 2D image based on the texture target. */
+ unsigned layer_size_in_bytes[R300_MAX_TEXTURE_LEVELS];
- /* Size of one zslice or face based on the texture target */
- unsigned layer_size[R300_MAX_TEXTURE_LEVELS];
+ /* Total size of this texture, in bytes,
+ * derived from the texture properties. */
+ unsigned size_in_bytes;
- /* Whether the mipmap level is macrotiled. */
- enum r300_buffer_tiling mip_macrotile[R300_MAX_TEXTURE_LEVELS];
+ /* Total size of the buffer backing this texture, in bytes.
+ * It must be >= size. */
+ unsigned buffer_size_in_bytes;
/**
* If non-zero, override the natural texture layout with
@@ -350,16 +366,24 @@ struct r300_texture {
*
* \sa r300_texture_get_stride
*/
- unsigned stride_override;
+ unsigned stride_in_bytes_override;
- /* Total size of this texture, in bytes. */
- unsigned size;
+ /* Whether this texture has non-power-of-two dimensions.
+ * It can be either a regular texture or a rectangle one. */
+ boolean is_npot;
- /* Whether this texture has non-power-of-two dimensions
- * or a user-specified pitch.
- * It can be either a regular texture or a rectangle one.
- */
- boolean uses_pitch;
+ /* This flag says that hardware must use the stride for addressing
+ * instead of the width. */
+ boolean uses_stride_addressing;
+
+ /* Whether CBZB fast color clear is allowed on the miplevel. */
+ boolean cbzb_allowed[R300_MAX_TEXTURE_LEVELS];
+};
+
+struct r300_texture {
+ struct r300_texture_desc desc;
+
+ enum r300_buffer_domain domain;
/* Pipe buffer backing this texture. */
struct r300_winsys_buffer *buffer;
@@ -370,8 +394,11 @@ struct r300_texture {
/* All bits should be filled in. */
struct r300_texture_fb_state fb_state;
- /* Buffer tiling */
- enum r300_buffer_tiling microtile, macrotile;
+ /* hyper-z memory allocs */
+ struct mem_block *hiz_mem[R300_MAX_TEXTURE_LEVELS];
+ struct mem_block *zmask_mem[R300_MAX_TEXTURE_LEVELS];
+ boolean zmask_in_use[R300_MAX_TEXTURE_LEVELS];
+ boolean hiz_in_use[R300_MAX_TEXTURE_LEVELS];
/* This is the level tiling flags were last time set for.
* It's used to prevent redundant tiling-flags changes from happening.*/
@@ -498,6 +525,10 @@ struct r300_context {
struct r300_atom texture_cache_inval;
/* GPU flush. */
struct r300_atom gpu_flush;
+ /* HiZ clear */
+ struct r300_atom hiz_clear;
+ /* zmask clear */
+ struct r300_atom zmask_clear;
/* Invariant state. This must be emitted to get the engine started. */
struct r300_atom invariant_state;
@@ -510,6 +541,8 @@ struct r300_context {
struct r300_vertex_element_state *velems;
bool any_user_vbs;
+ struct pipe_index_buffer index_buffer;
+
/* Vertex info for Draw. */
struct vertex_info vertex_info;
@@ -533,8 +566,16 @@ struct r300_context {
boolean two_sided_color;
/* Incompatible vertex buffer layout? (misaligned stride or buffer_offset) */
boolean incompatible_vb_layout;
-
+#define R300_Z_COMPRESS_44 1
+#define RV350_Z_COMPRESS_88 2
+ int z_compression;
boolean cbzb_clear;
+ boolean z_decomp_rd;
+
+ /* two mem block managers for hiz/zmask ram space */
+ struct mem_block *hiz_mm;
+ struct mem_block *zmask_mm;
+
/* upload managers */
struct u_upload_mgr *upload_vb;
struct u_upload_mgr *upload_ib;
@@ -586,6 +627,12 @@ void r300_init_render_functions(struct r300_context *r300);
void r300_init_state_functions(struct r300_context* r300);
void r300_init_resource_functions(struct r300_context* r300);
+/* r300_blit.c */
+void r300_flush_depth_stencil(struct pipe_context *pipe,
+ struct pipe_resource *dst,
+ struct pipe_subresource subdst,
+ unsigned zslice);
+
/* r300_query.c */
void r300_resume_query(struct r300_context *r300,
struct r300_query *query);
@@ -605,7 +652,8 @@ void r300_plug_in_stencil_ref_fallback(struct r300_context *r300);
/* r300_state.c */
enum r300_fb_state_change {
R300_CHANGED_FB_STATE = 0,
- R300_CHANGED_CBZB_FLAG
+ R300_CHANGED_CBZB_FLAG,
+ R300_CHANGED_ZCLEAR_FLAG
};
void r300_mark_fb_state_dirty(struct r300_context *r300,
diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h
index 3beb625d43..c194d6a1b0 100644
--- a/src/gallium/drivers/r300/r300_cs.h
+++ b/src/gallium/drivers/r300/r300_cs.h
@@ -136,8 +136,8 @@
#define WRITE_CS_TABLE(values, count) do { \
CS_DEBUG(assert(cs_count == 0);) \
- memcpy(cs_copy->ptr + cs_copy->cdw, values, count * 4); \
- cs_copy->cdw += count; \
+ memcpy(cs_copy->ptr + cs_copy->cdw, (values), (count) * 4); \
+ cs_copy->cdw += (count); \
} while (0)
#endif /* R300_CS_H */
diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c
index 31d4e14681..c3e157e99a 100644
--- a/src/gallium/drivers/r300/r300_debug.c
+++ b/src/gallium/drivers/r300/r300_debug.c
@@ -38,11 +38,13 @@ static const struct debug_named_value debug_options[] = {
{ "fall", DBG_FALL, "Fallbacks (for debugging)" },
{ "rs", DBG_RS, "Rasterizer (for debugging)" },
{ "fb", DBG_FB, "Framebuffer (for debugging)" },
+ { "cbzb", DBG_CBZB, "Fast color clear info (for debugging)" },
{ "fakeocc", DBG_FAKE_OCC, "Use fake occlusion queries (for debugging)" },
{ "anisohq", DBG_ANISOHQ, "High quality anisotropic filtering (for benchmarking)" },
{ "notiling", DBG_NO_TILING, "Disable tiling (for benchmarking)" },
{ "noimmd", DBG_NO_IMMD, "Disable immediate mode (for benchmarking)" },
{ "stats", DBG_STATS, "Gather statistics" },
+ { "hyperz", DBG_HYPERZ, "HyperZ (for debugging)" },
/* must be last */
DEBUG_NAMED_VALUE_END
diff --git a/src/gallium/drivers/r300/r300_defines.h b/src/gallium/drivers/r300/r300_defines.h
index d510d80a7b..896aeef395 100644
--- a/src/gallium/drivers/r300/r300_defines.h
+++ b/src/gallium/drivers/r300/r300_defines.h
@@ -36,7 +36,10 @@
enum r300_buffer_tiling {
R300_BUFFER_LINEAR = 0,
R300_BUFFER_TILED,
- R300_BUFFER_SQUARETILED
+ R300_BUFFER_SQUARETILED,
+
+ R300_BUFFER_UNKNOWN,
+ R300_BUFFER_SELECT_LAYOUT = R300_BUFFER_UNKNOWN
};
enum r300_buffer_domain { /* bitfield */
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 36a26a7871..d0fd45349e 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_mm.h"
#include "util/u_simple_list.h"
#include "r300_context.h"
@@ -329,6 +330,7 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state;
struct r300_surface* surf;
unsigned i;
+ boolean has_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
CS_LOCALS(r300);
BEGIN_CS(size);
@@ -364,6 +366,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
OUT_CS_RELOC(surf->buffer, surf->cbzb_pitch, 0, surf->domain);
+
+ DBG(r300, DBG_CBZB,
+ "CBZB clearing cbuf %08x %08x\n", surf->cbzb_format,
+ surf->cbzb_pitch);
}
/* Set up a zbuffer. */
else if (fb->zsbuf) {
@@ -377,15 +383,32 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain);
- /* HiZ RAM. */
- if (r300->screen->caps.has_hiz) {
- OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0);
- OUT_CS_REG(R300_ZB_HIZ_PITCH, 0);
+ if (has_hyperz) {
+ uint32_t surf_pitch;
+ struct r300_texture *tex;
+ int level = surf->base.level;
+ tex = r300_texture(surf->base.texture);
+
+ surf_pitch = surf->pitch & R300_DEPTHPITCH_MASK;
+ /* HiZ RAM. */
+ if (r300->screen->caps.hiz_ram) {
+ if (tex->hiz_mem[level]) {
+ OUT_CS_REG(R300_ZB_HIZ_OFFSET, tex->hiz_mem[level]->ofs << 2);
+ OUT_CS_REG(R300_ZB_HIZ_PITCH, surf_pitch);
+ } else {
+ OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0);
+ OUT_CS_REG(R300_ZB_HIZ_PITCH, 0);
+ }
+ }
+ /* Z Mask RAM. (compressed zbuffer) */
+ if (tex->zmask_mem[level]) {
+ OUT_CS_REG(R300_ZB_ZMASK_OFFSET, tex->zmask_mem[level]->ofs << 2);
+ OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf_pitch);
+ } else {
+ OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0);
+ OUT_CS_REG(R300_ZB_ZMASK_PITCH, 0);
+ }
}
-
- /* Z Mask RAM. (compressed zbuffer) */
- OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0);
- OUT_CS_REG(R300_ZB_ZMASK_PITCH, 0);
}
END_CS;
@@ -394,8 +417,12 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
void r300_emit_hyperz_state(struct r300_context *r300,
unsigned size, void *state)
{
+ struct r300_hyperz_state *z = state;
CS_LOCALS(r300);
- WRITE_CS_TABLE(state, size);
+ if (z->flush)
+ WRITE_CS_TABLE(&z->cb_flush_begin, size);
+ else
+ WRITE_CS_TABLE(&z->cb_begin, size - 2);
}
void r300_emit_hyperz_end(struct r300_context *r300)
@@ -403,9 +430,11 @@ void r300_emit_hyperz_end(struct r300_context *r300)
struct r300_hyperz_state z =
*(struct r300_hyperz_state*)r300->hyperz_state.state;
+ z.flush = 1;
z.zb_bw_cntl = 0;
z.zb_depthclearvalue = 0;
z.sc_hyperz = R300_SC_HYPERZ_ADJ_2;
+ z.gb_z_peq_config = 0;
r300_emit_hyperz_state(r300, r300->hyperz_state.size, &z);
}
@@ -907,6 +936,22 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state)
OUT_CS_TABLE(data, 4);
}
}
+
+ /* Emit flow control instructions. */
+ if (code->num_fc_ops) {
+
+ OUT_CS_REG(R300_VAP_PVS_FLOW_CNTL_OPC, code->fc_ops);
+ if (r300screen->caps.is_r500) {
+ OUT_CS_REG_SEQ(R500_VAP_PVS_FLOW_CNTL_ADDRS_LW_0, code->num_fc_ops * 2);
+ OUT_CS_TABLE(code->fc_op_addrs.r500, code->num_fc_ops * 2);
+ } else {
+ OUT_CS_REG_SEQ(R300_VAP_PVS_FLOW_CNTL_ADDRS_0, code->num_fc_ops);
+ OUT_CS_TABLE(code->fc_op_addrs.r300, code->num_fc_ops);
+ }
+ OUT_CS_REG_SEQ(R300_VAP_PVS_FLOW_CNTL_LOOP_INDEX_0, code->num_fc_ops);
+ OUT_CS_TABLE(code->fc_loop_index, code->num_fc_ops);
+ }
+
END_CS;
}
@@ -943,6 +988,111 @@ void r300_emit_viewport_state(struct r300_context* r300,
END_CS;
}
+static void r300_emit_hiz_line_clear(struct r300_context *r300, int start, uint16_t count, uint32_t val)
+{
+ CS_LOCALS(r300);
+ BEGIN_CS(4);
+ OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_HIZ, 2);
+ OUT_CS(start);
+ OUT_CS(count);
+ OUT_CS(val);
+ END_CS;
+}
+
+static void r300_emit_zmask_line_clear(struct r300_context *r300, int start, uint16_t count, uint32_t val)
+{
+ CS_LOCALS(r300);
+ BEGIN_CS(4);
+ OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_ZMASK, 2);
+ OUT_CS(start);
+ OUT_CS(count);
+ OUT_CS(val);
+ END_CS;
+}
+
+#define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y))
+
+void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state)
+{
+ struct pipe_framebuffer_state *fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+ struct r300_hyperz_state *z =
+ (struct r300_hyperz_state*)r300->hyperz_state.state;
+ struct r300_screen* r300screen = r300->screen;
+ uint32_t stride, offset = 0, height, offset_shift;
+ struct r300_texture* tex;
+ int i;
+
+ tex = r300_texture(fb->zsbuf->texture);
+
+ offset = tex->hiz_mem[fb->zsbuf->level]->ofs;
+ stride = tex->desc.stride_in_pixels[fb->zsbuf->level];
+
+ /* convert from pixels to 4x4 blocks */
+ stride = ALIGN_DIVUP(stride, 4);
+
+ stride = ALIGN_DIVUP(stride, r300screen->caps.num_frag_pipes);
+ /* there are 4 blocks per dwords */
+ stride = ALIGN_DIVUP(stride, 4);
+
+ height = ALIGN_DIVUP(fb->zsbuf->height, 4);
+
+ offset_shift = 2;
+ offset_shift += (r300screen->caps.num_frag_pipes / 2);
+
+ for (i = 0; i < height; i++) {
+ offset = i * stride;
+ offset <<= offset_shift;
+ r300_emit_hiz_line_clear(r300, offset, stride, 0xffffffff);
+ }
+ z->current_func = -1;
+
+ /* Mark the current zbuffer's hiz ram as in use. */
+ tex->hiz_in_use[fb->zsbuf->level] = TRUE;
+}
+
+void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state)
+{
+ struct pipe_framebuffer_state *fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+ struct r300_screen* r300screen = r300->screen;
+ uint32_t stride, offset = 0;
+ struct r300_texture* tex;
+ uint32_t i, height;
+ int mult, offset_shift;
+
+ tex = r300_texture(fb->zsbuf->texture);
+ stride = tex->desc.stride_in_pixels[fb->zsbuf->level];
+
+ offset = tex->zmask_mem[fb->zsbuf->level]->ofs;
+
+ if (r300->z_compression == RV350_Z_COMPRESS_88)
+ mult = 8;
+ else
+ mult = 4;
+
+ height = ALIGN_DIVUP(fb->zsbuf->height, mult);
+
+ offset_shift = 4;
+ offset_shift += (r300screen->caps.num_frag_pipes / 2);
+ stride = ALIGN_DIVUP(stride, r300screen->caps.num_frag_pipes);
+
+ /* okay have width in pixels - divide by block width */
+ stride = ALIGN_DIVUP(stride, mult);
+ /* have width in blocks - divide by number of fragment pipes screen width */
+ /* 16 blocks per dword */
+ stride = ALIGN_DIVUP(stride, 16);
+
+ for (i = 0; i < height; i++) {
+ offset = i * stride;
+ offset <<= offset_shift;
+ r300_emit_zmask_line_clear(r300, offset, stride, 0x0);//0xffffffff);
+ }
+
+ /* Mark the current zbuffer's zmask as in use. */
+ tex->zmask_in_use[fb->zsbuf->level] = TRUE;
+}
+
void r300_emit_ztop_state(struct r300_context* r300,
unsigned size, void* state)
{
@@ -1062,6 +1212,17 @@ unsigned r300_get_num_dirty_dwords(struct r300_context *r300)
return dwords;
}
+unsigned r300_get_num_cs_end_dwords(struct r300_context *r300)
+{
+ unsigned dwords = 0;
+
+ /* Emitted in flush. */
+ dwords += 26; /* emit_query_end */
+ dwords += r300->hyperz_state.size + 2; /* emit_hyperz_end + zcache flush */
+
+ return dwords;
+}
+
/* Emit all dirty state. */
void r300_emit_dirty_state(struct r300_context* r300)
{
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 5d05039669..bae2525634 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -112,7 +112,11 @@ void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, voi
void r300_emit_invariant_state(struct r300_context *r300,
unsigned size, void *state);
+void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state);
+void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state);
+
unsigned r300_get_num_dirty_dwords(struct r300_context *r300);
+unsigned r300_get_num_cs_end_dwords(struct r300_context *r300);
/* Emit all dirty state. */
void r300_emit_dirty_state(struct r300_context* r300);
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index ae7b5759e7..fe182b6615 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -43,14 +43,6 @@ static void r300_flush(struct pipe_context* pipe,
u_upload_flush(r300->upload_vb);
u_upload_flush(r300->upload_ib);
- /* 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.
- *
- * Of course, the best thing is to kill Draw with fire. :3 */
- if (r300->draw && !r300->draw->flushing) {
- draw_flush(r300->draw);
- }
-
if (r300->dirty_hw) {
r300_emit_hyperz_end(r300);
r300_emit_query_end(r300);
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c
index b145ded639..2a0c30620a 100644
--- a/src/gallium/drivers/r300/r300_fs.c
+++ b/src/gallium/drivers/r300/r300_fs.c
@@ -72,6 +72,11 @@ void r300_shader_read_fs_inputs(struct tgsi_shader_info* info,
fs_inputs->wpos = i;
break;
+ case TGSI_SEMANTIC_FACE:
+ assert(index == 0);
+ fs_inputs->face = i;
+ break;
+
default:
fprintf(stderr, "r300: FP: Unknown input semantic: %i\n",
info->input_semantic_name[i]);
@@ -120,6 +125,9 @@ static void allocate_hardware_inputs(
allocate(mydata, inputs->color[i], reg++);
}
}
+ if (inputs->face != ATTR_UNUSED) {
+ allocate(mydata, inputs->face, reg++);
+ }
for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
if (inputs->generic[i] != ATTR_UNUSED) {
allocate(mydata, inputs->generic[i], reg++);
@@ -173,7 +181,7 @@ static void get_external_state(
t = (struct r300_texture*)texstate->sampler_views[i]->base.texture;
/* XXX this should probably take into account STR, not just S. */
- if (t->uses_pitch) {
+ if (t->desc.is_npot) {
switch (s->state.wrap_s) {
case PIPE_TEX_WRAP_REPEAT:
state->unit[i].wrap_mode = RC_WRAP_REPEAT;
@@ -248,13 +256,18 @@ static void r300_emit_fs_code_to_buffer(
shader->cb_code_size = 19 +
((code->inst_end + 1) * 6) +
- imm_count * 7;
+ imm_count * 7 +
+ code->int_constant_count * 2;
NEW_CB(shader->cb_code, shader->cb_code_size);
OUT_CB_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
OUT_CB_REG(R500_US_PIXSIZE, code->max_temp_idx);
OUT_CB_REG(R500_US_FC_CTRL, code->us_fc_ctrl);
- OUT_CB_REG(R500_US_CODE_RANGE,
+ for(i = 0; i < code->int_constant_count; i++){
+ OUT_CB_REG(R500_US_FC_INT_CONST_0 + (i * 4),
+ code->int_constants[i]);
+ }
+ OUT_CB_REG(R500_US_CODE_RANGE,
R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end));
OUT_CB_REG(R500_US_CODE_OFFSET, 0);
OUT_CB_REG(R500_US_CODE_ADDR,
@@ -355,13 +368,14 @@ static void r300_translate_fragment_shader(
{
struct r300_fragment_program_compiler compiler;
struct tgsi_to_rc ttr;
- int wpos;
+ int wpos, face;
unsigned i;
tgsi_scan_shader(tokens, &shader->info);
r300_shader_read_fs_inputs(&shader->info, &shader->inputs);
wpos = shader->inputs.wpos;
+ face = shader->inputs.face;
/* Setup the compiler. */
memset(&compiler, 0, sizeof(compiler));
@@ -378,7 +392,7 @@ static void r300_translate_fragment_shader(
find_output_registers(&compiler, shader);
if (compiler.Base.Debug) {
- debug_printf("r300: Initial fragment program\n");
+ DBG(r300, DBG_FP, "r300: Initial fragment program\n");
tgsi_dump(tokens, 0);
}
@@ -401,6 +415,10 @@ static void r300_translate_fragment_shader(
rc_transform_fragment_wpos(&compiler.Base, wpos, wpos, TRUE);
}
+ if (face != ATTR_UNUSED) {
+ rc_transform_fragment_face(&compiler.Base, face);
+ }
+
/* Invoke the compiler */
r3xx_compile_fragment_program(&compiler);
@@ -413,7 +431,7 @@ static void r300_translate_fragment_shader(
}
if (compiler.Base.Error) {
- fprintf(stderr, "r300 FP: Compiler Error:\n%sUsing a dummy shader"
+ DBG(r300, DBG_FP, "r300 FP: Compiler Error:\n%sUsing a dummy shader"
" instead.\nIf there's an 'unknown opcode' message, please"
" file a bug report and attach this log.\n", compiler.Base.ErrorMsg);
diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c
index e952895601..811b5646e1 100644
--- a/src/gallium/drivers/r300/r300_hyperz.c
+++ b/src/gallium/drivers/r300/r300_hyperz.c
@@ -25,21 +25,170 @@
#include "r300_hyperz.h"
#include "r300_reg.h"
#include "r300_fs.h"
+#include "r300_winsys.h"
+#include "util/u_format.h"
+#include "util/u_mm.h"
+
+/*
+ HiZ rules - taken from various docs
+ 1. HiZ only works on depth values
+ 2. Cannot HiZ if stencil fail or zfail is !KEEP
+ 3. on R300/400, HiZ is disabled if depth test is EQUAL
+ 4. comparison changes without clears usually mean disabling HiZ
+*/
/*****************************************************************************/
/* The HyperZ setup */
/*****************************************************************************/
+static bool r300_get_sc_hz_max(struct r300_context *r300)
+{
+ struct r300_dsa_state *dsa_state = r300->dsa_state.state;
+ int func = dsa_state->z_stencil_control & 0x7;
+ int ret = R300_SC_HYPERZ_MIN;
+
+ if (func >= 4 && func <= 7)
+ ret = R300_SC_HYPERZ_MAX;
+ return ret;
+}
+
+static bool r300_zfunc_same_direction(int func1, int func2)
+{
+ /* func1 is less/lessthan */
+ if (func1 == 1 || func1 == 2)
+ if (func2 == 3 || func2 == 4 || func2 == 5)
+ return FALSE;
+
+ if (func2 == 1 || func2 == 2)
+ if (func1 == 4 || func1 == 5)
+ return FALSE;
+ return TRUE;
+}
+
+static int r300_get_hiz_min(struct r300_context *r300)
+{
+ struct r300_dsa_state *dsa_state = r300->dsa_state.state;
+ int func = dsa_state->z_stencil_control & 0x7;
+ int ret = R300_HIZ_MIN;
+
+ if (func == 1 || func == 2)
+ ret = R300_HIZ_MAX;
+ return ret;
+}
+
+static boolean r300_dsa_stencil_op_not_keep(struct pipe_stencil_state *s)
+{
+ if (s->enabled && (s->fail_op != PIPE_STENCIL_OP_KEEP ||
+ s->zfail_op != PIPE_STENCIL_OP_KEEP))
+ return TRUE;
+ return FALSE;
+}
+
+static boolean r300_can_hiz(struct r300_context *r300)
+{
+ struct r300_dsa_state *dsa_state = r300->dsa_state.state;
+ struct pipe_depth_stencil_alpha_state *dsa = &dsa_state->dsa;
+ struct r300_screen* r300screen = r300->screen;
+ struct r300_hyperz_state *z = r300->hyperz_state.state;
+
+ /* shader writes depth - no HiZ */
+ if (r300_fragment_shader_writes_depth(r300_fs(r300))) /* (5) */
+ return FALSE;
+
+ if (r300->query_current)
+ return FALSE;
+ /* if stencil fail/zfail op is not KEEP */
+ if (r300_dsa_stencil_op_not_keep(&dsa->stencil[0]) ||
+ r300_dsa_stencil_op_not_keep(&dsa->stencil[1]))
+ return FALSE;
+
+ if (dsa->depth.enabled) {
+ /* if depth func is EQUAL pre-r500 */
+ if (dsa->depth.func == PIPE_FUNC_EQUAL && !r300screen->caps.is_r500)
+ return FALSE;
+ /* if depth func is NOTEQUAL */
+ if (dsa->depth.func == PIPE_FUNC_NOTEQUAL)
+ return FALSE;
+ }
+ /* depth comparison function - if just cleared save and return okay */
+ if (z->current_func == -1) {
+ int func = dsa_state->z_stencil_control & 0x7;
+ if (func != 0 && func != 7)
+ z->current_func = dsa_state->z_stencil_control & 0x7;
+ } else {
+ /* simple don't change */
+ if (!r300_zfunc_same_direction(z->current_func, (dsa_state->z_stencil_control & 0x7))) {
+ DBG(r300, DBG_HYPERZ, "z func changed direction - disabling hyper-z %d -> %d\n", z->current_func, dsa_state->z_stencil_control);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
static void r300_update_hyperz(struct r300_context* r300)
{
struct r300_hyperz_state *z =
(struct r300_hyperz_state*)r300->hyperz_state.state;
+ struct pipe_framebuffer_state *fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+ struct r300_texture *zstex =
+ fb->zsbuf ? r300_texture(fb->zsbuf->texture) : NULL;
+ boolean zmask_in_use = FALSE;
+ boolean hiz_in_use = FALSE;
+ z->gb_z_peq_config = 0;
z->zb_bw_cntl = 0;
z->sc_hyperz = R300_SC_HYPERZ_ADJ_2;
+ z->flush = 0;
- if (r300->cbzb_clear)
+ if (r300->cbzb_clear) {
z->zb_bw_cntl |= R300_ZB_CB_CLEAR_CACHE_LINE_WRITE_ONLY;
+ return;
+ }
+
+ if (!zstex)
+ return;
+
+ if (!r300->rws->get_value(r300->rws, R300_CAN_HYPERZ))
+ return;
+
+ zmask_in_use = zstex->zmask_in_use[fb->zsbuf->level];
+ hiz_in_use = zstex->hiz_in_use[fb->zsbuf->level];
+
+ /* Z fastfill. */
+ if (zmask_in_use) {
+ z->zb_bw_cntl |= R300_FAST_FILL_ENABLE; /* | R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE;*/
+ }
+
+ /* Zbuffer compression. */
+ if (zmask_in_use && r300->z_compression) {
+ z->zb_bw_cntl |= R300_RD_COMP_ENABLE;
+ if (r300->z_decomp_rd == false)
+ z->zb_bw_cntl |= R300_WR_COMP_ENABLE;
+ }
+ /* RV350 and up optimizations. */
+ /* The section 10.4.9 in the docs is a lie. */
+ if (r300->z_compression == RV350_Z_COMPRESS_88)
+ z->gb_z_peq_config |= R300_GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_8_8;
+
+ if (hiz_in_use) {
+ bool can_hiz = r300_can_hiz(r300);
+ if (can_hiz) {
+ z->zb_bw_cntl |= R300_HIZ_ENABLE;
+ z->sc_hyperz |= R300_SC_HYPERZ_ENABLE;
+ z->sc_hyperz |= r300_get_sc_hz_max(r300);
+ z->zb_bw_cntl |= r300_get_hiz_min(r300);
+ }
+ }
+
+ /* R500-specific features and optimizations. */
+ if (r300->screen->caps.is_r500) {
+ z->zb_bw_cntl |= R500_HIZ_FP_EXP_BITS_3;
+ z->zb_bw_cntl |=
+ R500_HIZ_EQUAL_REJECT_ENABLE |
+ R500_PEQ_PACKING_ENABLE |
+ R500_COVERED_PTR_MASKING_ENABLE;
+ }
}
/*****************************************************************************/
@@ -126,15 +275,121 @@ static void r300_update_ztop(struct r300_context* r300)
} else {
ztop_state->z_buffer_top = R300_ZTOP_ENABLE;
}
-
if (ztop_state->z_buffer_top != old_ztop)
r300->ztop_state.dirty = TRUE;
}
+#define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y))
+
+static void r300_update_hiz_clear(struct r300_context *r300)
+{
+ struct pipe_framebuffer_state *fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+ uint32_t height;
+
+ height = ALIGN_DIVUP(fb->zsbuf->height, 4);
+ r300->hiz_clear.size = height * 4;
+}
+
+static void r300_update_zmask_clear(struct r300_context *r300)
+{
+ struct pipe_framebuffer_state *fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+ uint32_t height;
+ int mult;
+
+ if (r300->z_compression == RV350_Z_COMPRESS_88)
+ mult = 8;
+ else
+ mult = 4;
+
+ height = ALIGN_DIVUP(fb->zsbuf->height, mult);
+
+ r300->zmask_clear.size = height * 4;
+}
+
void r300_update_hyperz_state(struct r300_context* r300)
{
r300_update_ztop(r300);
if (r300->hyperz_state.dirty) {
r300_update_hyperz(r300);
}
+
+ if (r300->hiz_clear.dirty) {
+ r300_update_hiz_clear(r300);
+ }
+ if (r300->zmask_clear.dirty) {
+ r300_update_zmask_clear(r300);
+ }
+}
+
+void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf)
+{
+ struct r300_texture *tex;
+ uint32_t zsize, ndw;
+ int level = surf->base.level;
+
+ tex = r300_texture(surf->base.texture);
+
+ if (tex->hiz_mem[level])
+ return;
+
+ zsize = tex->desc.layer_size_in_bytes[level];
+ zsize /= util_format_get_blocksize(tex->desc.b.b.format);
+ ndw = ALIGN_DIVUP(zsize, 64);
+
+ tex->hiz_mem[level] = u_mmAllocMem(r300->hiz_mm, ndw, 0, 0);
+ return;
+}
+
+void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf, int compress)
+{
+ int bsize = 256;
+ uint32_t zsize, ndw;
+ int level = surf->base.level;
+ struct r300_texture *tex;
+
+ tex = r300_texture(surf->base.texture);
+
+ /* We currently don't handle decompression for 3D textures and cubemaps
+ * correctly. */
+ if (tex->desc.b.b.target != PIPE_TEXTURE_1D &&
+ tex->desc.b.b.target != PIPE_TEXTURE_2D)
+ return;
+
+ if (tex->zmask_mem[level])
+ return;
+
+ zsize = tex->desc.layer_size_in_bytes[level];
+ zsize /= util_format_get_blocksize(tex->desc.b.b.format);
+
+ /* each zmask dword represents 16 4x4 blocks - which is 256 pixels
+ or 16 8x8 depending on the gb peq flag = 1024 pixels */
+ if (compress == RV350_Z_COMPRESS_88)
+ bsize = 1024;
+
+ ndw = ALIGN_DIVUP(zsize, bsize);
+ tex->zmask_mem[level] = u_mmAllocMem(r300->zmask_mm, ndw, 0, 0);
+ return;
+}
+
+void r300_hyperz_init_mm(struct r300_context *r300)
+{
+ struct r300_screen* r300screen = r300->screen;
+ int frag_pipes = r300screen->caps.num_frag_pipes;
+
+ if (r300screen->caps.hiz_ram)
+ r300->hiz_mm = u_mmInit(0, r300screen->caps.hiz_ram * frag_pipes);
+
+ r300->zmask_mm = u_mmInit(0, r300screen->caps.zmask_ram * frag_pipes);
+}
+
+void r300_hyperz_destroy_mm(struct r300_context *r300)
+{
+ struct r300_screen* r300screen = r300->screen;
+
+ if (r300screen->caps.hiz_ram)
+ u_mmDestroy(r300->hiz_mm);
+
+ u_mmDestroy(r300->zmask_mm);
}
diff --git a/src/gallium/drivers/r300/r300_hyperz.h b/src/gallium/drivers/r300/r300_hyperz.h
index 3df5053b89..09e1ff6625 100644
--- a/src/gallium/drivers/r300/r300_hyperz.h
+++ b/src/gallium/drivers/r300/r300_hyperz.h
@@ -27,4 +27,9 @@ struct r300_context;
void r300_update_hyperz_state(struct r300_context* r300);
+void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf);
+void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf, int compress);
+
+void r300_hyperz_init_mm(struct r300_context *r300);
+void r300_hyperz_destroy_mm(struct r300_context *r300);
#endif
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index 2acc1a903e..60d3b600cb 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -496,6 +496,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R300_VAP_GB_HORZ_CLIP_ADJ 0x2228
#define R300_VAP_GB_HORZ_DISC_ADJ 0x222c
+#define R300_VAP_PVS_FLOW_CNTL_ADDRS_0 0x2230
+#define R300_PVS_FC_ACT_ADRS(x) ((x) << 0)
+#define R300_PVS_FC_LOOP_CNT_JMP_INST(x) ((x) << 8)
+#define R300_PVS_FC_LAST_INST(x) ((x) << 16)
+#define R300_PVS_FC_RTN_INST(x) ((x) << 24)
+
/* gap */
/* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
@@ -514,6 +520,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_2288_R300 0x00750000 /* -- nh */
# define R300_2288_RV350 0x0000FFFF /* -- Vladimir */
+#define R300_VAP_PVS_FLOW_CNTL_LOOP_INDEX_0 0x2290
+#define R300_PVS_FC_LOOP_INIT_VAL(x) ((x) << 0)
+#define R300_PVS_FC_LOOP_STEP_VAL(x) ((x) << 8)
+
/* gap */
/* Addresses are relative to the vertex program instruction area of the
@@ -548,6 +558,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R300_VAP_PVS_CODE_CNTL_1 0x22D8
# define R300_PVS_LAST_VTX_SRC_INST_SHIFT 0
#define R300_VAP_PVS_FLOW_CNTL_OPC 0x22DC
+#define R300_VAP_PVS_FC_OPC_JUMP(x) (1 << (2 * (x)))
+#define R300_VAP_PVS_FC_OPC_LOOP(x) (2 << (2 * (x)))
+#define R300_VAP_PVS_FC_OPC_JSR(x) (3 << (2 * (x)))
/* The entire range from 0x2300 to 0x2AC inclusive seems to be used for
* immediate vertices
@@ -564,6 +577,14 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* write 0 to indicate end of packet? */
#define R300_VAP_VTX_END_OF_PKT 0x24AC
+#define R500_VAP_PVS_FLOW_CNTL_ADDRS_LW_0 0x2500
+#define R500_PVS_FC_ACT_ADRS(x) ((x) << 0)
+#define R500_PVS_FC_LOOP_CNT_JMP_INST(x) ((x) << 16)
+
+#define R500_VAP_PVS_FLOW_CNTL_ADDRS_UW_0 0x2504
+#define R500_PVS_FC_LAST_INST(x) ((x) << 0)
+#define R500_PVS_FC_RTN_INST(x) ((x) << 16)
+
/* gap */
/* These are values from r300_reg/r300_reg.h - they are known to be correct
@@ -3436,6 +3457,7 @@ enum {
# define R300_VBPNTR_SIZE1(x) (((x) >> 2) << 16)
# define R300_VBPNTR_STRIDE1(x) (((x) >> 2) << 24)
+#define R300_PACKET3_3D_CLEAR_ZMASK 0x00003200
#define R300_PACKET3_INDX_BUFFER 0x00003300
# define R300_INDX_BUFFER_DST_SHIFT 0
# define R300_INDX_BUFFER_SKIP_SHIFT 16
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index bae02135da..86b11ca045 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -186,20 +186,14 @@ enum r300_prepare_flags {
* \param cs_dwords The number of dwords to reserve in CS.
* \param aos_offset The offset passed to emit_aos.
* \param index_bias The index bias to emit.
- * \param end_cs_dwords The number of free dwords which must be available
- * at the end of CS after drawing in case the CS space
- * management is performed by a draw_* function manually.
- * The parameter may be NULL.
*/
static void r300_prepare_for_rendering(struct r300_context *r300,
enum r300_prepare_flags flags,
struct pipe_resource *index_buffer,
unsigned cs_dwords,
int aos_offset,
- int index_bias,
- unsigned *end_cs_dwords)
+ int index_bias)
{
- unsigned end_dwords = 0;
boolean flushed = FALSE;
boolean first_draw = flags & PREP_FIRST_DRAW;
boolean emit_aos = flags & PREP_EMIT_AOS;
@@ -221,11 +215,7 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
cs_dwords += 7; /* emit_aos_swtcl */
}
- /* Emitted in flush. */
- end_dwords += 26; /* emit_query_end */
- end_dwords += r300->hyperz_state.size; /* emit_hyperz_end */
-
- cs_dwords += end_dwords;
+ cs_dwords += r300_get_num_cs_end_dwords(r300);
/* Reserve requested CS space. */
if (cs_dwords > (r300->cs->ndw - r300->cs->cdw)) {
@@ -250,9 +240,6 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
if (emit_aos_swtcl)
r300_emit_aos_swtcl(r300, indexed);
}
-
- if (end_cs_dwords)
- *end_cs_dwords = end_dwords;
}
static boolean immd_is_good_idea(struct r300_context *r300,
@@ -353,7 +340,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
dwords = 9 + count * vertex_size;
- r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0, NULL);
+ r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0);
BEGIN_CS(dwords);
OUT_CS_REG(R300_GA_COLOR_CONTROL,
@@ -533,7 +520,7 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
/* 15 dwords for emit_draw_elements */
r300_prepare_for_rendering(r300,
PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED,
- indexBuffer, 15, buffer_offset, indexBias, NULL);
+ indexBuffer, 15, buffer_offset, indexBias);
if (alt_num_verts || count <= 65535) {
r300_emit_draw_elements(r300, indexBuffer, indexSize,
@@ -552,7 +539,7 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
if (count) {
r300_prepare_for_rendering(r300,
PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED,
- indexBuffer, 15, buffer_offset, indexBias, NULL);
+ indexBuffer, 15, buffer_offset, indexBias);
}
} while (count);
}
@@ -566,19 +553,6 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
}
}
-/* Simple helpers for context setup. Should probably be moved to util. */
-static void r300_draw_elements(struct pipe_context* pipe,
- struct pipe_resource* indexBuffer,
- unsigned indexSize, int indexBias, unsigned mode,
- unsigned start, unsigned count)
-{
- struct r300_context *r300 = r300_context(pipe);
-
- pipe->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
- 0, r300->vertex_buffer_max_index,
- mode, start, count);
-}
-
static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
unsigned start, unsigned count)
{
@@ -610,7 +584,7 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
} else {
/* 9 spare dwords for emit_draw_arrays. */
r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS,
- NULL, 9, start, 0, NULL);
+ NULL, 9, start, 0);
if (alt_num_verts || count <= 65535) {
r300_emit_draw_arrays(r300, mode, count);
@@ -626,7 +600,7 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
if (count) {
r300_prepare_for_rendering(r300,
PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9,
- start, 0, NULL);
+ start, 0);
}
} while (count);
}
@@ -638,111 +612,104 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
}
}
-/****************************************************************************
- * The rest of this file is for SW TCL rendering only. Please be polite and *
- * keep these functions separated so that they are easier to locate. ~C. *
- ***************************************************************************/
-
-/* SW TCL arrays, using Draw. */
-static void r300_swtcl_draw_arrays(struct pipe_context* pipe,
- unsigned mode,
- unsigned start,
- unsigned count)
+static void r300_draw_vbo(struct pipe_context* pipe,
+ const struct pipe_draw_info *info)
{
struct r300_context* r300 = r300_context(pipe);
- struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
- int i;
- if (r300->skip_rendering) {
- return;
+ if (info->indexed && r300->index_buffer.buffer) {
+ unsigned offset;
+
+ assert(r300->index_buffer.offset % r300->index_buffer.index_size == 0);
+ offset = r300->index_buffer.offset / r300->index_buffer.index_size;
+
+ r300_draw_range_elements(pipe,
+ r300->index_buffer.buffer,
+ r300->index_buffer.index_size,
+ info->index_bias,
+ info->min_index,
+ info->max_index,
+ info->mode,
+ info->start + offset,
+ info->count);
}
-
- if (!u_trim_pipe_prim(mode, &count)) {
- return;
- }
-
- r300_update_derived_state(r300);
-
- for (i = 0; i < r300->vertex_buffer_count; i++) {
- void* buf = pipe_buffer_map(pipe,
- r300->vertex_buffer[i].buffer,
- PIPE_TRANSFER_READ,
- &vb_transfer[i]);
- draw_set_mapped_vertex_buffer(r300->draw, i, buf);
- }
-
- draw_set_mapped_element_buffer(r300->draw, 0, 0, NULL);
-
- draw_arrays(r300->draw, mode, start, count);
-
- /* XXX Not sure whether this is the best fix.
- * It prevents CS from being rejected and weird assertion failures. */
- draw_flush(r300->draw);
-
- for (i = 0; i < r300->vertex_buffer_count; i++) {
- pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
- vb_transfer[i]);
- draw_set_mapped_vertex_buffer(r300->draw, i, NULL);
+ else {
+ r300_draw_arrays(pipe,
+ info->mode,
+ info->start,
+ info->count);
}
}
+/****************************************************************************
+ * The rest of this file is for SW TCL rendering only. Please be polite and *
+ * keep these functions separated so that they are easier to locate. ~C. *
+ ***************************************************************************/
+
/* SW TCL elements, using Draw. */
-static void r300_swtcl_draw_range_elements(struct pipe_context* pipe,
- struct pipe_resource* indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count)
+static void r300_swtcl_draw_vbo(struct pipe_context* pipe,
+ const struct pipe_draw_info *info)
{
struct r300_context* r300 = r300_context(pipe);
struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
- struct pipe_transfer *ib_transfer;
+ struct pipe_transfer *ib_transfer = NULL;
+ unsigned count = info->count;
int i;
- void* indices;
+ void* indices = NULL;
if (r300->skip_rendering) {
return;
}
- if (!u_trim_pipe_prim(mode, &count)) {
+ if (!u_trim_pipe_prim(info->mode, &count)) {
return;
}
r300_update_derived_state(r300);
for (i = 0; i < r300->vertex_buffer_count; i++) {
- void* buf = pipe_buffer_map(pipe,
- r300->vertex_buffer[i].buffer,
- PIPE_TRANSFER_READ,
- &vb_transfer[i]);
- draw_set_mapped_vertex_buffer(r300->draw, i, buf);
+ if (r300->vertex_buffer[i].buffer) {
+ void *buf = pipe_buffer_map(pipe,
+ r300->vertex_buffer[i].buffer,
+ PIPE_TRANSFER_READ,
+ &vb_transfer[i]);
+ draw_set_mapped_vertex_buffer(r300->draw, i, buf);
+ }
}
- indices = pipe_buffer_map(pipe, indexBuffer,
- PIPE_TRANSFER_READ, &ib_transfer);
- draw_set_mapped_element_buffer_range(r300->draw, indexSize, indexBias,
- minIndex, maxIndex, indices);
+ if (info->indexed && r300->index_buffer.buffer) {
+ indices = pipe_buffer_map(pipe, r300->index_buffer.buffer,
+ PIPE_TRANSFER_READ, &ib_transfer);
+ if (indices)
+ indices = (void *) ((char *) indices + r300->index_buffer.offset);
+ }
- draw_arrays(r300->draw, mode, start, count);
+ draw_set_mapped_element_buffer_range(r300->draw, (indices) ?
+ r300->index_buffer.index_size : 0,
+ info->index_bias,
+ info->min_index,
+ info->max_index,
+ indices);
+
+ draw_arrays(r300->draw, info->mode, info->start, count);
/* XXX Not sure whether this is the best fix.
* It prevents CS from being rejected and weird assertion failures. */
draw_flush(r300->draw);
for (i = 0; i < r300->vertex_buffer_count; i++) {
- pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
- vb_transfer[i]);
- draw_set_mapped_vertex_buffer(r300->draw, i, NULL);
+ if (r300->vertex_buffer[i].buffer) {
+ pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
+ vb_transfer[i]);
+ draw_set_mapped_vertex_buffer(r300->draw, i, NULL);
+ }
}
- pipe_buffer_unmap(pipe, indexBuffer,
- ib_transfer);
- draw_set_mapped_element_buffer_range(r300->draw, 0, 0,
- start, start + count - 1,
- NULL);
+ if (ib_transfer) {
+ pipe_buffer_unmap(pipe, r300->index_buffer.buffer, ib_transfer);
+ draw_set_mapped_element_buffer_range(r300->draw, 0, 0, info->start,
+ info->start + count - 1, NULL);
+ }
}
/* Object for rendering using Draw. */
@@ -820,6 +787,8 @@ static void* r300_render_map_vertices(struct vbuf_render* render)
PIPE_TRANSFER_WRITE,
&r300render->vbo_transfer);
+ assert(r300render->vbo_ptr);
+
return ((uint8_t*)r300render->vbo_ptr + r300render->vbo_offset);
}
@@ -872,7 +841,7 @@ static void r300_render_draw_arrays(struct vbuf_render* render,
(void) i; (void) ptr;
r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL,
- NULL, dwords, 0, 0, NULL);
+ NULL, dwords, 0, 0);
DBG(r300, DBG_DRAW, "r300: render_draw_arrays (count: %d)\n", count);
@@ -925,7 +894,8 @@ static void r300_render_draw_elements(struct vbuf_render* render,
* indices than it can fit in CS. */
r300_prepare_for_rendering(r300,
PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | PREP_INDEXED,
- NULL, 256, 0, 0, &end_cs_dwords);
+ NULL, 256, 0, 0);
+ end_cs_dwords = r300_get_num_cs_end_dwords(r300);
while (count) {
free_dwords = r300->cs->ndw - r300->cs->cdw;
@@ -955,7 +925,8 @@ static void r300_render_draw_elements(struct vbuf_render* render,
if (count) {
r300_prepare_for_rendering(r300,
PREP_EMIT_AOS_SWTCL | PREP_INDEXED,
- NULL, 256, 0, 0, &end_cs_dwords);
+ NULL, 256, 0, 0);
+ end_cs_dwords = r300_get_num_cs_end_dwords(r300);
}
}
}
@@ -1049,7 +1020,7 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter,
r300->clip_state.dirty = FALSE;
r300->viewport_state.dirty = FALSE;
- r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0, NULL);
+ r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0);
DBG(r300, DBG_DRAW, "r300: draw_rectangle\n");
@@ -1141,16 +1112,11 @@ static void r300_resource_resolve(struct pipe_context* pipe,
void r300_init_render_functions(struct r300_context *r300)
{
- /* Set generic functions. */
- r300->context.draw_elements = r300_draw_elements;
-
/* Set draw functions based on presence of HW TCL. */
if (r300->screen->caps.has_tcl) {
- r300->context.draw_arrays = r300_draw_arrays;
- r300->context.draw_range_elements = r300_draw_range_elements;
+ r300->context.draw_vbo = r300_draw_vbo;
} else {
- r300->context.draw_arrays = r300_swtcl_draw_arrays;
- r300->context.draw_range_elements = r300_swtcl_draw_range_elements;
+ r300->context.draw_vbo = r300_swtcl_draw_vbo;
}
r300->context.resource_resolve = r300_resource_resolve;
diff --git a/src/gallium/drivers/r300/r300_render_stencilref.c b/src/gallium/drivers/r300/r300_render_stencilref.c
index 9a6b4e12ff..1f035d64a2 100644
--- a/src/gallium/drivers/r300/r300_render_stencilref.c
+++ b/src/gallium/drivers/r300/r300_render_stencilref.c
@@ -34,13 +34,8 @@
#include "r300_reg.h"
struct r300_stencilref_context {
- void (*draw_arrays)(struct pipe_context *pipe,
- unsigned mode, unsigned start, unsigned count);
-
- void (*draw_range_elements)(
- struct pipe_context *pipe, struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex,
- unsigned mode, unsigned start, unsigned count);
+ void (*draw_vbo)(struct pipe_context *pipe,
+ const struct pipe_draw_info *info);
uint32_t rs_cull_mode;
uint32_t zb_stencilrefmask;
@@ -105,41 +100,19 @@ static void r300_stencilref_end(struct r300_context *r300)
r300->dsa_state.dirty = TRUE;
}
-static void r300_stencilref_draw_arrays(struct pipe_context *pipe, unsigned mode,
- unsigned start, unsigned count)
-{
- struct r300_context *r300 = r300_context(pipe);
- struct r300_stencilref_context *sr = r300->stencilref_fallback;
-
- if (!r300_stencilref_needed(r300)) {
- sr->draw_arrays(pipe, mode, start, count);
- } else {
- r300_stencilref_begin(r300);
- sr->draw_arrays(pipe, mode, start, count);
- r300_stencilref_switch_side(r300);
- sr->draw_arrays(pipe, mode, start, count);
- r300_stencilref_end(r300);
- }
-}
-
-static void r300_stencilref_draw_range_elements(
- struct pipe_context *pipe, struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex,
- unsigned mode, unsigned start, unsigned count)
+static void r300_stencilref_draw_vbo(struct pipe_context *pipe,
+ const struct pipe_draw_info *info)
{
struct r300_context *r300 = r300_context(pipe);
struct r300_stencilref_context *sr = r300->stencilref_fallback;
if (!r300_stencilref_needed(r300)) {
- sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
- minIndex, maxIndex, mode, start, count);
+ sr->draw_vbo(pipe, info);
} else {
r300_stencilref_begin(r300);
- sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
- minIndex, maxIndex, mode, start, count);
+ sr->draw_vbo(pipe, info);
r300_stencilref_switch_side(r300);
- sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
- minIndex, maxIndex, mode, start, count);
+ sr->draw_vbo(pipe, info);
r300_stencilref_end(r300);
}
}
@@ -148,11 +121,9 @@ void r300_plug_in_stencil_ref_fallback(struct r300_context *r300)
{
r300->stencilref_fallback = CALLOC_STRUCT(r300_stencilref_context);
- /* Save original draw functions. */
- r300->stencilref_fallback->draw_arrays = r300->context.draw_arrays;
- r300->stencilref_fallback->draw_range_elements = r300->context.draw_range_elements;
+ /* Save original draw function. */
+ r300->stencilref_fallback->draw_vbo = r300->context.draw_vbo;
- /* Override the draw functions. */
- r300->context.draw_arrays = r300_stencilref_draw_arrays;
- r300->context.draw_range_elements = r300_stencilref_draw_range_elements;
+ /* Override the draw function. */
+ r300->context.draw_vbo = r300_stencilref_draw_vbo;
}
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index 5a11b98eb6..1e4edcdbc3 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -115,7 +115,6 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
case PIPE_CAP_TEXTURE_SWIZZLE:
- case PIPE_CAP_DEPTH_CLAMP:
return 1;
/* Unsupported features (boolean caps). */
@@ -124,6 +123,8 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_CONT_SUPPORTED:
case PIPE_CAP_INDEP_BLEND_ENABLE:
case PIPE_CAP_INDEP_BLEND_FUNC:
+ case PIPE_CAP_DEPTH_CLAMP: /* XXX implemented, but breaks Regnum Online */
+ case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
return 0;
/* Texturing. */
@@ -150,9 +151,6 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_MAX_CONST_BUFFER_SIZE:
return 256;
- case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
- return 1;
-
/* Fragment coordinate conventions. */
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
@@ -257,8 +255,6 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
uint32_t retval = 0;
boolean is_r500 = r300_screen(screen)->caps.is_r500;
boolean is_r400 = r300_screen(screen)->caps.is_r400;
- boolean is_z24 = format == PIPE_FORMAT_X8Z24_UNORM ||
- format == PIPE_FORMAT_S8_USCALED_Z24_UNORM;
boolean is_color2101010 = format == PIPE_FORMAT_R10G10B10A2_UNORM ||
format == PIPE_FORMAT_R10G10B10X2_SNORM ||
format == PIPE_FORMAT_B10G10R10A2_UNORM ||
@@ -281,11 +277,14 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
case 3:
case 4:
case 6:
+ return FALSE;
+#if 0
if (usage != PIPE_BIND_RENDER_TARGET ||
!util_format_is_rgba8_variant(
util_format_description(format))) {
return FALSE;
}
+#endif
break;
default:
return FALSE;
@@ -293,8 +292,6 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
/* Check sampler format support. */
if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
- /* Z24 cannot be sampled from on non-r5xx. */
- (is_r500 || !is_z24) &&
/* ATI1N is r5xx-only. */
(is_r500 || !is_ati1n) &&
/* ATI2N is supported on r4xx-r5xx. */
diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h
index edc494ff6c..13a3320b99 100644
--- a/src/gallium/drivers/r300/r300_screen.h
+++ b/src/gallium/drivers/r300/r300_screen.h
@@ -90,6 +90,8 @@ r300_winsys_screen(struct pipe_screen *screen) {
#define DBG_FALL (1 << 8)
#define DBG_FB (1 << 9)
#define DBG_RS_BLOCK (1 << 10)
+#define DBG_CBZB (1 << 11)
+#define DBG_HYPERZ (1 << 12)
/* Features. */
#define DBG_ANISOHQ (1 << 16)
#define DBG_NO_TILING (1 << 17)
diff --git a/src/gallium/drivers/r300/r300_shader_semantics.h b/src/gallium/drivers/r300/r300_shader_semantics.h
index cb7a37033f..4be23e64ce 100644
--- a/src/gallium/drivers/r300/r300_shader_semantics.h
+++ b/src/gallium/drivers/r300/r300_shader_semantics.h
@@ -38,6 +38,7 @@ struct r300_shader_semantics {
int psize;
int color[ATTR_COLOR_COUNT];
int bcolor[ATTR_COLOR_COUNT];
+ int face;
int generic[ATTR_GENERIC_COUNT];
int fog;
int wpos;
@@ -50,6 +51,7 @@ static INLINE void r300_shader_semantics_reset(
info->pos = ATTR_UNUSED;
info->psize = ATTR_UNUSED;
+ info->face = ATTR_UNUSED;
info->fog = ATTR_UNUSED;
info->wpos = ATTR_UNUSED;
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index f52265b1c0..239edd98e3 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -25,6 +25,7 @@
#include "util/u_blitter.h"
#include "util/u_math.h"
+#include "util/u_mm.h"
#include "util/u_memory.h"
#include "util/u_pack_color.h"
@@ -43,6 +44,7 @@
#include "r300_texture.h"
#include "r300_vs.h"
#include "r300_winsys.h"
+#include "r300_hyperz.h"
/* r300_state: Functions used to intialize state context by translating
* Gallium state objects into semi-native r300 state objects. */
@@ -446,7 +448,6 @@ static void r300_set_clip_state(struct pipe_context* pipe,
r300->clip_state.dirty = TRUE;
} else {
- draw_flush(r300->draw);
draw_set_clip_state(r300->draw, state);
}
}
@@ -473,14 +474,14 @@ static void*
dsa->dsa = *state;
- /* Depth test setup. */
+ /* Depth test setup. - separate write mask depth for decomp flush */
+ if (state->depth.writemask) {
+ dsa->z_buffer_control |= R300_Z_WRITE_ENABLE;
+ }
+
if (state->depth.enabled) {
dsa->z_buffer_control |= R300_Z_ENABLE;
- if (state->depth.writemask) {
- dsa->z_buffer_control |= R300_Z_WRITE_ENABLE;
- }
-
dsa->z_stencil_control |=
(r300_translate_depth_stencil_function(state->depth.func) <<
R300_Z_FUNC_SHIFT);
@@ -593,6 +594,7 @@ static void r300_bind_dsa_state(struct pipe_context* pipe,
UPDATE_STATE(state, r300->dsa_state);
+ r300->hyperz_state.dirty = TRUE; /* Will be updated before the emission. */
r300_dsa_inject_stencilref(r300);
}
@@ -619,7 +621,8 @@ static void r300_tex_set_tiling_flags(struct r300_context *r300,
{
/* Check if the macrotile flag needs to be changed.
* Skip changing the flags otherwise. */
- if (tex->mip_macrotile[tex->surface_level] != tex->mip_macrotile[level]) {
+ if (tex->desc.macrotile[tex->surface_level] !=
+ tex->desc.macrotile[level]) {
/* Tiling determines how DRM treats the buffer data.
* We must flush CS when changing it if the buffer is referenced. */
if (r300->rws->cs_is_buffer_referenced(r300->cs,
@@ -627,8 +630,8 @@ static void r300_tex_set_tiling_flags(struct r300_context *r300,
r300->context.flush(&r300->context, 0, NULL);
r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
- tex->microtile, tex->mip_macrotile[level],
- tex->pitch[0] * util_format_get_blocksize(tex->b.b.format));
+ tex->desc.microtile, tex->desc.macrotile[level],
+ tex->desc.stride_in_bytes[0]);
tex->surface_level = level;
}
@@ -670,8 +673,10 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index,
surf->zslice, surf->face, surf->level,
util_format_short_name(surf->format),
- rtex->macrotile ? "YES" : " NO", rtex->microtile ? "YES" : " NO",
- rtex->hwpitch[0], tex->width0, tex->height0, tex->depth0,
+ rtex->desc.macrotile[0] ? "YES" : " NO",
+ rtex->desc.microtile ? "YES" : " NO",
+ rtex->desc.stride_in_pixels[0],
+ tex->width0, tex->height0, tex->depth0,
tex->last_level, util_format_short_name(tex->format));
}
@@ -679,6 +684,7 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
enum r300_fb_state_change change)
{
struct pipe_framebuffer_state *state = r300->fb_state.state;
+ boolean has_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
/* What is marked as dirty depends on the enum r300_fb_state_change. */
r300->gpu_flush.dirty = TRUE;
@@ -695,8 +701,11 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
if (r300->cbzb_clear)
r300->fb_state.size += 10;
- else if (state->zsbuf)
- r300->fb_state.size += r300->screen->caps.has_hiz ? 18 : 14;
+ else if (state->zsbuf) {
+ r300->fb_state.size += 10;
+ if (has_hyperz)
+ r300->fb_state.size += r300->screen->caps.hiz_ram ? 8 : 4;
+ }
/* The size of the rest of atoms stays the same. */
}
@@ -708,8 +717,10 @@ static void
struct r300_context* r300 = r300_context(pipe);
struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state;
struct pipe_framebuffer_state *old_state = r300->fb_state.state;
+ boolean has_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
unsigned max_width, max_height, i;
uint32_t zbuffer_bpp = 0;
+ int blocksize;
if (r300->screen->caps.is_r500) {
max_width = max_height = 4096;
@@ -725,10 +736,6 @@ static void
return;
}
- if (r300->draw) {
- draw_flush(r300->draw);
- }
-
/* If nr_cbufs is changed from zero to non-zero or vice versa... */
if (!!old_state->nr_cbufs != !!state->nr_cbufs) {
r300->blend_state.dirty = TRUE;
@@ -745,20 +752,50 @@ static void
r300_mark_fb_state_dirty(r300, R300_CHANGED_FB_STATE);
- /* Polygon offset depends on the zbuffer bit depth. */
- if (state->zsbuf && r300->polygon_offset_enabled) {
- switch (util_format_get_blocksize(state->zsbuf->texture->format)) {
- case 2:
- zbuffer_bpp = 16;
- break;
- case 4:
- zbuffer_bpp = 24;
- break;
+ r300->z_compression = false;
+
+ if (state->zsbuf) {
+ blocksize = util_format_get_blocksize(state->zsbuf->texture->format);
+ switch (blocksize) {
+ case 2:
+ zbuffer_bpp = 16;
+ break;
+ case 4:
+ zbuffer_bpp = 24;
+ break;
+ }
+ if (has_hyperz) {
+ struct r300_surface *zs_surf = r300_surface(state->zsbuf);
+ struct r300_texture *tex;
+ int compress = r300->screen->caps.is_rv350 ? RV350_Z_COMPRESS_88 : R300_Z_COMPRESS_44;
+ int level = zs_surf->base.level;
+
+ tex = r300_texture(zs_surf->base.texture);
+
+ /* work out whether we can support hiz on this buffer */
+ r300_hiz_alloc_block(r300, zs_surf);
+
+ /* work out whether we can support zmask features on this buffer */
+ r300_zmask_alloc_block(r300, zs_surf, compress);
+
+ if (tex->zmask_mem[level]) {
+ /* compression causes hangs on 16-bit */
+ if (zbuffer_bpp == 24)
+ r300->z_compression = compress;
+ }
+ DBG(r300, DBG_HYPERZ,
+ "hyper-z features: hiz: %d @ %08x z-compression: %d z-fastfill: %d @ %08x\n", tex->hiz_mem[level] ? 1 : 0,
+ tex->hiz_mem[level] ? tex->hiz_mem[level]->ofs : 0xdeadbeef,
+ r300->z_compression, tex->zmask_mem[level] ? 1 : 0,
+ tex->zmask_mem[level] ? tex->zmask_mem[level]->ofs : 0xdeadbeef);
}
+ /* Polygon offset depends on the zbuffer bit depth. */
if (r300->zbuffer_bpp != zbuffer_bpp) {
r300->zbuffer_bpp = zbuffer_bpp;
- r300->rs_state.dirty = TRUE;
+
+ if (r300->polygon_offset_enabled)
+ r300->rs_state.dirty = TRUE;
}
}
@@ -1016,7 +1053,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
for (i = 0; i < 8; i++) {
if (state->sprite_coord_enable & (1 << i))
stuffing_enable |=
- R300_GB_TEX_STR << (R300_GB_TEX0_SOURCE_SHIFT + (i*2));
+ R300_GB_TEX_ST << (R300_GB_TEX0_SOURCE_SHIFT + (i*2));
}
point_texcoord_left = 0.0f;
@@ -1093,14 +1130,11 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
boolean last_two_sided_color = r300->two_sided_color;
if (r300->draw && rs) {
- draw_flush(r300->draw);
draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state);
}
if (rs) {
- r300->polygon_offset_enabled = (rs->rs.offset_point ||
- rs->rs.offset_line ||
- rs->rs.offset_tri);
+ r300->polygon_offset_enabled = rs->polygon_offset_enable;
r300->sprite_coord_enable = rs->rs.sprite_coord_enable;
r300->two_sided_color = rs->rs.light_twoside;
} else {
@@ -1293,7 +1327,7 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
/* Set the texrect factor in the fragment shader.
* Needed for RECT and NPOT fallback. */
texture = r300_texture(views[i]->texture);
- if (texture->uses_pitch) {
+ if (texture->desc.is_npot) {
r300->fs_rc_constant_state.dirty = TRUE;
}
@@ -1327,6 +1361,7 @@ r300_create_sampler_view(struct pipe_context *pipe,
{
struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view);
struct r300_texture *tex = r300_texture(texture);
+ boolean is_r500 = r300_screen(pipe->screen)->caps.is_r500;
if (view) {
view->base = *templ;
@@ -1342,8 +1377,9 @@ r300_create_sampler_view(struct pipe_context *pipe,
view->format = tex->tx_format;
view->format.format1 |= r300_translate_texformat(templ->format,
- view->swizzle);
- if (r300_screen(pipe->screen)->caps.is_r500) {
+ view->swizzle,
+ is_r500);
+ if (is_r500) {
view->format.format2 |= r500_tx_format_msb_bit(templ->format);
}
}
@@ -1380,7 +1416,6 @@ static void r300_set_viewport_state(struct pipe_context* pipe,
r300->viewport = *state;
if (r300->draw) {
- draw_flush(r300->draw);
draw_set_viewport_state(r300->draw, state);
viewport->vte_control = R300_VTX_XY_FMT | R300_VTX_Z_FMT;
return;
@@ -1481,7 +1516,6 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
} else {
/* SW TCL. */
- draw_flush(r300->draw);
draw_set_vertex_buffers(r300->draw, count, buffers);
}
@@ -1500,6 +1534,23 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
r300->vertex_buffer_count = count;
}
+static void r300_set_index_buffer(struct pipe_context* pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ if (ib) {
+ pipe_resource_reference(&r300->index_buffer.buffer, ib->buffer);
+ memcpy(&r300->index_buffer, ib, sizeof(r300->index_buffer));
+ }
+ else {
+ pipe_resource_reference(&r300->index_buffer.buffer, NULL);
+ memset(&r300->index_buffer, 0, sizeof(r300->index_buffer));
+ }
+
+ /* TODO make this more like a state */
+}
+
/* Initialize the PSC tables. */
static void r300_vertex_psc(struct r300_vertex_element_state *velems)
{
@@ -1649,7 +1700,6 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe,
r300->velems = velems;
if (r300->draw) {
- draw_flush(r300->draw);
draw_set_vertex_elements(r300->draw, velems->count, velems->velem);
return;
}
@@ -1701,10 +1751,12 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */
if (r300->screen->caps.has_tcl) {
+ unsigned fc_op_dwords = r300->screen->caps.is_r500 ? 3 : 2;
r300->vs_state.dirty = TRUE;
r300->vs_state.size =
vs->code.length + 9 +
- (vs->immediates_count ? vs->immediates_count * 4 + 3 : 0);
+ (vs->immediates_count ? vs->immediates_count * 4 + 3 : 0) +
+ (vs->code.num_fc_ops ? vs->code.num_fc_ops * fc_op_dwords + 4 : 0);
if (vs->externals_count) {
r300->vs_constants.dirty = TRUE;
@@ -1715,7 +1767,6 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
r300->pvs_flush.dirty = TRUE;
} else {
- draw_flush(r300->draw);
draw_bind_vertex_shader(r300->draw,
(struct draw_vertex_shader*)vs->draw_vs);
}
@@ -1847,6 +1898,7 @@ void r300_init_state_functions(struct r300_context* r300)
r300->context.set_viewport_state = r300_set_viewport_state;
r300->context.set_vertex_buffers = r300_set_vertex_buffers;
+ r300->context.set_index_buffer = r300_set_index_buffer;
r300->context.create_vertex_elements_state = r300_create_vertex_elements_state;
r300->context.bind_vertex_elements_state = r300_bind_vertex_elements_state;
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index 2ef9766578..4a63ed7fc1 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -46,6 +46,11 @@ enum r300_rs_swizzle {
SWIZ_0001,
};
+enum r300_rs_col_write_type {
+ WRITE_COLOR = 0,
+ WRITE_FACE
+};
+
static void r300_draw_emit_attrib(struct r300_context* r300,
enum attrib_emit emit,
enum interp_mode interp,
@@ -203,8 +208,10 @@ static void r300_rs_col(struct r300_rs_block* rs, int id, int ptr,
rs->inst[id] |= R300_RS_INST_COL_ID(id);
}
-static void r300_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset)
+static void r300_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset,
+ enum r300_rs_col_write_type type)
{
+ assert(type != WRITE_COLOR);
rs->inst[id] |= R300_RS_INST_COL_CN_WRITE |
R300_RS_INST_COL_ADDR(fp_offset);
}
@@ -213,19 +220,19 @@ static void r300_rs_tex(struct r300_rs_block* rs, int id, int ptr,
enum r300_rs_swizzle swiz)
{
if (swiz == SWIZ_X001) {
- rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) |
+ rs->ip[id] |= R300_RS_TEX_PTR(ptr) |
R300_RS_SEL_S(R300_RS_SEL_C0) |
R300_RS_SEL_T(R300_RS_SEL_K0) |
R300_RS_SEL_R(R300_RS_SEL_K0) |
R300_RS_SEL_Q(R300_RS_SEL_K1);
} else if (swiz == SWIZ_XY01) {
- rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) |
+ rs->ip[id] |= R300_RS_TEX_PTR(ptr) |
R300_RS_SEL_S(R300_RS_SEL_C0) |
R300_RS_SEL_T(R300_RS_SEL_C1) |
R300_RS_SEL_R(R300_RS_SEL_K0) |
R300_RS_SEL_Q(R300_RS_SEL_K1);
} else {
- rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) |
+ rs->ip[id] |= R300_RS_TEX_PTR(ptr) |
R300_RS_SEL_S(R300_RS_SEL_C0) |
R300_RS_SEL_T(R300_RS_SEL_C1) |
R300_RS_SEL_R(R300_RS_SEL_C2) |
@@ -252,32 +259,36 @@ static void r500_rs_col(struct r300_rs_block* rs, int id, int ptr,
rs->inst[id] |= R500_RS_INST_COL_ID(id);
}
-static void r500_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset)
+static void r500_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset,
+ enum r300_rs_col_write_type type)
{
- rs->inst[id] |= R500_RS_INST_COL_CN_WRITE |
- R500_RS_INST_COL_ADDR(fp_offset);
+ if (type == WRITE_FACE)
+ rs->inst[id] |= R500_RS_INST_COL_CN_WRITE_BACKFACE |
+ R500_RS_INST_COL_ADDR(fp_offset);
+ else
+ rs->inst[id] |= R500_RS_INST_COL_CN_WRITE |
+ R500_RS_INST_COL_ADDR(fp_offset);
+
}
static void r500_rs_tex(struct r300_rs_block* rs, int id, int ptr,
enum r300_rs_swizzle swiz)
{
- int rs_tex_comp = ptr*4;
-
if (swiz == SWIZ_X001) {
- rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) |
+ rs->ip[id] |= R500_RS_SEL_S(ptr) |
R500_RS_SEL_T(R500_RS_IP_PTR_K0) |
R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
R500_RS_SEL_Q(R500_RS_IP_PTR_K1);
} else if (swiz == SWIZ_XY01) {
- rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) |
- R500_RS_SEL_T(rs_tex_comp + 1) |
+ rs->ip[id] |= R500_RS_SEL_S(ptr) |
+ R500_RS_SEL_T(ptr + 1) |
R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
R500_RS_SEL_Q(R500_RS_IP_PTR_K1);
} else {
- rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) |
- R500_RS_SEL_T(rs_tex_comp + 1) |
- R500_RS_SEL_R(rs_tex_comp + 2) |
- R500_RS_SEL_Q(rs_tex_comp + 3);
+ rs->ip[id] |= R500_RS_SEL_S(ptr) |
+ R500_RS_SEL_T(ptr + 1) |
+ R500_RS_SEL_R(ptr + 2) |
+ R500_RS_SEL_Q(ptr + 3);
}
rs->inst[id] |= R500_RS_INST_TEX_ID(id);
}
@@ -305,9 +316,9 @@ static void r300_update_rs_block(struct r300_context *r300)
struct r300_shader_semantics *vs_outputs = &vs->outputs;
struct r300_shader_semantics *fs_inputs = &r300_fs(r300)->shader->inputs;
struct r300_rs_block rs = {0};
- int i, col_count = 0, tex_count = 0, fp_offset = 0, count, loc = 0;
+ int i, col_count = 0, tex_count = 0, fp_offset = 0, count, loc = 0, tex_ptr = 0;
void (*rX00_rs_col)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
- void (*rX00_rs_col_write)(struct r300_rs_block*, int, int);
+ void (*rX00_rs_col_write)(struct r300_rs_block*, int, int, enum r300_rs_col_write_type);
void (*rX00_rs_tex)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
void (*rX00_rs_tex_write)(struct r300_rs_block*, int, int);
boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
@@ -326,6 +337,11 @@ static void r300_update_rs_block(struct r300_context *r300)
rX00_rs_tex_write = r300_rs_tex_write;
}
+ /* 0x5555 copied from classic, which means:
+ * Select user color 0 for COLOR0 up to COLOR7.
+ * What the hell does that mean? */
+ rs.vap_vtx_state_cntl = 0x5555;
+
/* The position is always present in VAP. */
rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_POS;
rs.vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
@@ -352,7 +368,7 @@ static void r300_update_rs_block(struct r300_context *r300)
/* Write it to the FS input register if it's needed by the FS. */
if (fs_inputs->color[i] != ATTR_UNUSED) {
- rX00_rs_col_write(&rs, col_count, fp_offset);
+ rX00_rs_col_write(&rs, col_count, fp_offset, WRITE_COLOR);
fp_offset++;
DBG(r300, DBG_RS,
@@ -393,12 +409,31 @@ static void r300_update_rs_block(struct r300_context *r300)
stream_loc_notcl[loc++] = 6 + tex_count;
/* Rasterize it. */
- rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_XYZW);
+ rX00_rs_tex(&rs, tex_count, tex_ptr, SWIZ_XYZW);
tex_count++;
+ tex_ptr += 4;
}
}
}
+ /* gl_FrontFacing.
+ * Note that we can use either the two-sided color selection based on
+ * the front and back vertex shader colors, or gl_FrontFacing,
+ * but not both! It locks up otherwise.
+ *
+ * In Direct3D 9, the two-sided color selection can be used
+ * with shaders 2.0 only, while gl_FrontFacing can be used
+ * with shaders 3.0 only. The hardware apparently hasn't been designed
+ * to support both at the same time. */
+ if (r300->screen->caps.is_r500 && fs_inputs->face != ATTR_UNUSED &&
+ !(any_bcolor_used && r300->two_sided_color)) {
+ rX00_rs_col(&rs, col_count, col_count, SWIZ_XYZW);
+ rX00_rs_col_write(&rs, col_count, fp_offset, WRITE_FACE);
+ fp_offset++;
+ col_count++;
+ DBG(r300, DBG_RS, "r300: Rasterized FACE written to FS.\n");
+ }
+
/* Rasterize texture coordinates. */
for (i = 0; i < ATTR_GENERIC_COUNT && tex_count < 8; i++) {
bool sprite_coord = !!(r300->sprite_coord_enable & (1 << i));
@@ -412,7 +447,7 @@ static void r300_update_rs_block(struct r300_context *r300)
}
/* Rasterize it. */
- rX00_rs_tex(&rs, tex_count, tex_count,
+ rX00_rs_tex(&rs, tex_count, tex_ptr,
sprite_coord ? SWIZ_XY01 : SWIZ_XYZW);
/* Write it to the FS input register if it's needed by the FS. */
@@ -429,6 +464,7 @@ static void r300_update_rs_block(struct r300_context *r300)
i, sprite_coord ? " (sprite coord)" : "");
}
tex_count++;
+ tex_ptr += sprite_coord ? 2 : 4;
} else {
/* Skip the FS input register, leave it uninitialized. */
/* If we try to set it to (0,0,0,1), it will lock up. */
@@ -449,7 +485,7 @@ static void r300_update_rs_block(struct r300_context *r300)
stream_loc_notcl[loc++] = 6 + tex_count;
/* Rasterize it. */
- rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_X001);
+ rX00_rs_tex(&rs, tex_count, tex_ptr, SWIZ_X001);
/* Write it to the FS input register if it's needed by the FS. */
if (fs_inputs->fog != ATTR_UNUSED) {
@@ -461,6 +497,7 @@ static void r300_update_rs_block(struct r300_context *r300)
DBG(r300, DBG_RS, "r300: Rasterized fog unused.\n");
}
tex_count++;
+ tex_ptr += 4;
} else {
/* Skip the FS input register, leave it uninitialized. */
/* If we try to set it to (0,0,0,1), it will lock up. */
@@ -480,7 +517,7 @@ static void r300_update_rs_block(struct r300_context *r300)
stream_loc_notcl[loc++] = 6 + tex_count;
/* Rasterize it. */
- rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_XYZW);
+ rX00_rs_tex(&rs, tex_count, tex_ptr, SWIZ_XYZW);
/* Write it to the FS input register. */
rX00_rs_tex_write(&rs, tex_count, fp_offset);
@@ -489,6 +526,7 @@ static void r300_update_rs_block(struct r300_context *r300)
fp_offset++;
tex_count++;
+ tex_ptr += 4;
}
/* Invalidate the rest of the no-TCL (GA) stream locations. */
@@ -507,7 +545,7 @@ static void r300_update_rs_block(struct r300_context *r300)
DBG(r300, DBG_RS, "r300: --- Rasterizer status ---: colors: %i, "
"generics: %i.\n", col_count, tex_count);
- rs.count = (tex_count*4) | (col_count << R300_IC_COUNT_SHIFT) |
+ rs.count = MIN2(tex_ptr, 32) | (col_count << R300_IC_COUNT_SHIFT) |
R300_HIRES_EN;
count = MAX3(col_count, tex_count, 1);
@@ -528,15 +566,9 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
struct r300_sampler_state *sampler;
struct r300_sampler_view *view;
struct r300_texture *tex;
- unsigned min_level, max_level, i, size;
+ unsigned min_level, max_level, i, j, size;
unsigned count = MIN2(state->sampler_view_count,
state->sampler_state_count);
- unsigned char depth_swizzle[4] = {
- UTIL_FORMAT_SWIZZLE_X,
- UTIL_FORMAT_SWIZZLE_X,
- UTIL_FORMAT_SWIZZLE_X,
- UTIL_FORMAT_SWIZZLE_X
- };
/* The KIL opcode fix, see below. */
if (!count && !r300->screen->caps.is_r500)
@@ -563,14 +595,29 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
/* Assign a texture cache region. */
texstate->format.format1 |= view->texcache_region;
- /* If compare mode is disabled, the sampler view swizzles
- * are stored in the format.
- * Otherwise, swizzles must be applied after the compare mode
- * in the fragment shader. */
- if (util_format_is_depth_or_stencil(tex->b.b.format)) {
+ /* Depth textures are kinda special. */
+ if (util_format_is_depth_or_stencil(tex->desc.b.b.format)) {
+ unsigned char depth_swizzle[4];
+
+ if (!r300->screen->caps.is_r500 &&
+ util_format_get_blocksizebits(tex->desc.b.b.format) == 32) {
+ /* X24x8 is sampled as Y16X16 on r3xx-r4xx.
+ * The depth here is at the Y component. */
+ for (j = 0; j < 4; j++)
+ depth_swizzle[j] = UTIL_FORMAT_SWIZZLE_Y;
+ } else {
+ for (j = 0; j < 4; j++)
+ depth_swizzle[j] = UTIL_FORMAT_SWIZZLE_X;
+ }
+
+ /* If compare mode is disabled, sampler view swizzles
+ * are stored in the format.
+ * Otherwise, the swizzles must be applied after the compare
+ * mode in the fragment shader. */
if (sampler->state.compare_mode == PIPE_TEX_COMPARE_NONE) {
texstate->format.format1 |=
- r300_get_swizzle_combined(depth_swizzle, view->swizzle);
+ r300_get_swizzle_combined(depth_swizzle,
+ view->swizzle);
} else {
texstate->format.format1 |=
r300_get_swizzle_combined(depth_swizzle, 0);
@@ -578,12 +625,12 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
}
/* to emulate 1D textures through 2D ones correctly */
- if (tex->b.b.target == PIPE_TEXTURE_1D) {
+ if (tex->desc.b.b.target == PIPE_TEXTURE_1D) {
texstate->filter0 &= ~R300_TX_WRAP_T_MASK;
texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
}
- if (tex->uses_pitch) {
+ if (tex->desc.is_npot) {
/* NPOT textures don't support mip filter, unfortunately.
* This prevents incorrect rendering. */
texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK;
@@ -610,7 +657,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
/* determine min/max levels */
/* the MAX_MIP level is the largest (finest) one */
max_level = MIN3(sampler->max_lod + view->base.first_level,
- tex->b.b.last_level, view->base.last_level);
+ tex->desc.b.b.last_level, view->base.last_level);
min_level = MIN2(sampler->min_lod + view->base.first_level,
max_level);
texstate->format.format0 |= R300_TX_NUM_LEVELS(max_level);
@@ -665,8 +712,44 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
}
}
+/* We can't use compressed zbuffers as samplers. */
+static void r300_flush_depth_textures(struct r300_context *r300)
+{
+ struct r300_textures_state *state =
+ (struct r300_textures_state*)r300->textures_state.state;
+ unsigned i, level;
+ unsigned count = MIN2(state->sampler_view_count,
+ state->sampler_state_count);
+
+ if (r300->z_decomp_rd)
+ return;
+
+ for (i = 0; i < count; i++)
+ if (state->sampler_views[i] && state->sampler_states[i]) {
+ struct pipe_resource *tex = state->sampler_views[i]->base.texture;
+
+ if (tex->target == PIPE_TEXTURE_3D ||
+ tex->target == PIPE_TEXTURE_CUBE)
+ continue;
+
+ /* Ignore non-depth textures.
+ * Also ignore reinterpreted depth textures, e.g. resource_copy. */
+ if (!util_format_is_depth_or_stencil(tex->format))
+ continue;
+
+ for (level = 0; level <= tex->last_level; level++)
+ if (r300_texture(tex)->zmask_in_use[level]) {
+ /* We don't handle 3D textures and cubemaps yet. */
+ r300_flush_depth_stencil(&r300->context, tex,
+ u_subresource(0, level), 0);
+ }
+ }
+}
+
void r300_update_derived_state(struct r300_context* r300)
{
+ r300_flush_depth_textures(r300);
+
if (r300->textures_state.dirty) {
r300_merge_textures_and_samplers(r300);
}
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 5750bc4329..da8eadd3b5 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -26,6 +26,7 @@
#include "r300_context.h"
#include "r300_reg.h"
+#include "r300_texture_desc.h"
#include "r300_transfer.h"
#include "r300_screen.h"
#include "r300_winsys.h"
@@ -34,14 +35,10 @@
#include "util/u_format_s3tc.h"
#include "util/u_math.h"
#include "util/u_memory.h"
+#include "util/u_mm.h"
#include "pipe/p_screen.h"
-enum r300_dim {
- DIM_WIDTH = 0,
- DIM_HEIGHT = 1
-};
-
unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
const unsigned char *swizzle_view)
{
@@ -109,7 +106,8 @@ unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
* The FORMAT specifies how the texture sampler will treat the texture, and
* makes available X, Y, Z, W, ZERO, and ONE for swizzling. */
uint32_t r300_translate_texformat(enum pipe_format format,
- const unsigned char *swizzle_view)
+ const unsigned char *swizzle_view,
+ boolean is_r500)
{
uint32_t result = 0;
const struct util_format_description *desc;
@@ -134,7 +132,10 @@ uint32_t r300_translate_texformat(enum pipe_format format,
return R300_TX_FORMAT_X16;
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- return R500_TX_FORMAT_Y8X24;
+ if (is_r500)
+ return R500_TX_FORMAT_Y8X24;
+ else
+ return R300_TX_FORMAT_Y16X16;
default:
return ~0; /* Unsupported. */
}
@@ -537,26 +538,27 @@ boolean r300_is_zs_format_supported(enum pipe_format format)
boolean r300_is_sampler_format_supported(enum pipe_format format)
{
- return r300_translate_texformat(format, 0) != ~0;
+ return r300_translate_texformat(format, 0, TRUE) != ~0;
}
static void r300_texture_setup_immutable_state(struct r300_screen* screen,
struct r300_texture* tex)
{
struct r300_texture_format_state* f = &tex->tx_format;
- struct pipe_resource *pt = &tex->b.b;
+ struct pipe_resource *pt = &tex->desc.b.b;
boolean is_r500 = screen->caps.is_r500;
/* Set sampler state. */
f->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) |
R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff);
- if (tex->uses_pitch) {
+ if (tex->desc.uses_stride_addressing) {
/* rectangles love this */
f->format0 |= R300_TX_PITCH_EN;
- f->format2 = (tex->hwpitch[0] - 1) & 0x1fff;
+ f->format2 = (tex->desc.stride_in_pixels[0] - 1) & 0x1fff;
} else {
- /* power of two textures (3D, mipmaps, and no pitch) */
+ /* Power of two textures (3D, mipmaps, and no pitch),
+ * also NPOT textures with a width being POT. */
f->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf);
}
@@ -579,8 +581,8 @@ static void r300_texture_setup_immutable_state(struct r300_screen* screen,
}
}
- f->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) |
- R300_TXO_MICRO_TILE(tex->microtile);
+ f->tile_config = R300_TXO_MACRO_TILE(tex->desc.macrotile[0]) |
+ R300_TXO_MICRO_TILE(tex->desc.microtile);
}
static void r300_texture_setup_fb_state(struct r300_screen* screen,
@@ -589,23 +591,23 @@ static void r300_texture_setup_fb_state(struct r300_screen* screen,
unsigned i;
/* Set framebuffer state. */
- if (util_format_is_depth_or_stencil(tex->b.b.format)) {
- for (i = 0; i <= tex->b.b.last_level; i++) {
+ if (util_format_is_depth_or_stencil(tex->desc.b.b.format)) {
+ for (i = 0; i <= tex->desc.b.b.last_level; i++) {
tex->fb_state.pitch[i] =
- tex->hwpitch[i] |
- R300_DEPTHMACROTILE(tex->mip_macrotile[i]) |
- R300_DEPTHMICROTILE(tex->microtile);
+ tex->desc.stride_in_pixels[i] |
+ R300_DEPTHMACROTILE(tex->desc.macrotile[i]) |
+ R300_DEPTHMICROTILE(tex->desc.microtile);
}
- tex->fb_state.format = r300_translate_zsformat(tex->b.b.format);
+ tex->fb_state.format = r300_translate_zsformat(tex->desc.b.b.format);
} else {
- for (i = 0; i <= tex->b.b.last_level; i++) {
+ for (i = 0; i <= tex->desc.b.b.last_level; i++) {
tex->fb_state.pitch[i] =
- tex->hwpitch[i] |
- r300_translate_colorformat(tex->b.b.format) |
- R300_COLOR_TILE(tex->mip_macrotile[i]) |
- R300_COLOR_MICROTILE(tex->microtile);
+ tex->desc.stride_in_pixels[i] |
+ r300_translate_colorformat(tex->desc.b.b.format) |
+ R300_COLOR_TILE(tex->desc.macrotile[i]) |
+ R300_COLOR_MICROTILE(tex->desc.microtile);
}
- tex->fb_state.format = r300_translate_out_fmt(tex->b.b.format);
+ tex->fb_state.format = r300_translate_out_fmt(tex->desc.b.b.format);
}
}
@@ -625,282 +627,6 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen,
r300_texture_setup_fb_state(r300_screen(screen), r300_texture(tex));
}
-unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
- unsigned zslice, unsigned face)
-{
- unsigned offset = tex->offset[level];
-
- switch (tex->b.b.target) {
- case PIPE_TEXTURE_3D:
- assert(face == 0);
- return offset + zslice * tex->layer_size[level];
-
- case PIPE_TEXTURE_CUBE:
- assert(zslice == 0);
- return offset + face * tex->layer_size[level];
-
- default:
- assert(zslice == 0 && face == 0);
- return offset;
- }
-}
-
-/* Returns the number of pixels that the texture should be aligned to
- * in the given dimension. */
-static unsigned r300_get_pixel_alignment(struct r300_texture *tex,
- enum r300_buffer_tiling macrotile,
- enum r300_dim dim)
-{
- static const unsigned table[2][5][3][2] =
- {
- {
- /* Macro: linear linear linear
- Micro: 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 */
- },
- {
- /* Macro: tiled tiled tiled
- Micro: linear tiled square-tiled */
- {{256, 8}, {64, 32}, { 0, 0}}, /* 8 bits per pixel */
- {{128, 8}, {64, 16}, {32, 32}}, /* 16 bits per pixel */
- {{ 64, 8}, {32, 16}, { 0, 0}}, /* 32 bits per pixel */
- {{ 32, 8}, { 0, 0}, {16, 16}}, /* 64 bits per pixel */
- {{ 16, 8}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */
- }
- };
- static const unsigned aa_block[2] = {4, 8};
- unsigned res = 0;
- unsigned pixsize = util_format_get_blocksize(tex->b.b.format);
-
- assert(macrotile <= R300_BUFFER_TILED);
- assert(tex->microtile <= R300_BUFFER_SQUARETILED);
- assert(pixsize <= 16);
- assert(dim <= DIM_HEIGHT);
-
- if (tex->b.b.nr_samples > 1) {
- /* Multisampled textures have their own alignment scheme. */
- if (pixsize == 4)
- res = aa_block[dim];
- } else {
- /* Standard alignment. */
- res = table[macrotile][util_logbase2(pixsize)][tex->microtile][dim];
- }
-
- assert(res);
- return res;
-}
-
-/* Return true if macrotiling should be enabled on the miplevel. */
-static boolean r300_texture_macro_switch(struct r300_texture *tex,
- unsigned level,
- boolean rv350_mode,
- enum r300_dim dim)
-{
- unsigned tile, texdim;
-
- tile = r300_get_pixel_alignment(tex, R300_BUFFER_TILED, dim);
- if (dim == DIM_WIDTH) {
- texdim = u_minify(tex->b.b.width0, level);
- } else {
- texdim = u_minify(tex->b.b.height0, level);
- }
-
- /* See TX_FILTER1_n.MACRO_SWITCH. */
- if (rv350_mode) {
- return texdim >= tile;
- } else {
- return texdim > tile;
- }
-}
-
-/**
- * Return the stride, in bytes, of the texture images of the given texture
- * at the given level.
- */
-unsigned r300_texture_get_stride(struct r300_screen* screen,
- struct r300_texture* tex, unsigned level)
-{
- unsigned tile_width, width, stride;
-
- if (tex->stride_override)
- return tex->stride_override;
-
- /* Check the level. */
- if (level > tex->b.b.last_level) {
- SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n",
- __FUNCTION__, level, tex->b.b.last_level);
- return 0;
- }
-
- width = u_minify(tex->b.b.width0, level);
-
- if (util_format_is_plain(tex->b.b.format)) {
- tile_width = r300_get_pixel_alignment(tex, tex->mip_macrotile[level],
- DIM_WIDTH);
- width = align(width, tile_width);
-
- stride = util_format_get_stride(tex->b.b.format, width);
-
- /* Some IGPs need a minimum stride of 64 bytes, hmm...
- * This doesn't seem to apply to tiled textures, according to r300c. */
- if (!tex->microtile && !tex->mip_macrotile[level] &&
- (screen->caps.family == CHIP_FAMILY_RS600 ||
- screen->caps.family == CHIP_FAMILY_RS690 ||
- screen->caps.family == CHIP_FAMILY_RS740)) {
- return stride < 64 ? 64 : stride;
- }
-
- /* The alignment to 32 bytes is sort of implied by the layout... */
- return stride;
- } else {
- return align(util_format_get_stride(tex->b.b.format, width), 32);
- }
-}
-
-static unsigned r300_texture_get_nblocksy(struct r300_texture* tex,
- unsigned level)
-{
- unsigned height, tile_height;
-
- height = u_minify(tex->b.b.height0, level);
-
- if (util_format_is_plain(tex->b.b.format)) {
- tile_height = r300_get_pixel_alignment(tex, tex->mip_macrotile[level],
- DIM_HEIGHT);
- height = align(height, tile_height);
-
- /* This is needed for the kernel checker, unfortunately. */
- height = util_next_power_of_two(height);
- }
-
- return util_format_get_nblocksy(tex->b.b.format, height);
-}
-
-static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen,
- struct r300_texture *tex)
-{
- /* The kernels <= 2.6.34-rc4 compute the size of mipmapped 3D textures
- * incorrectly. This is a workaround to prevent CS from being rejected. */
-
- unsigned i, size;
-
- if (!screen->rws->get_value(screen->rws, R300_VID_DRM_2_3_0) &&
- tex->b.b.target == PIPE_TEXTURE_3D &&
- tex->b.b.last_level > 0) {
- size = 0;
-
- for (i = 0; i <= tex->b.b.last_level; i++) {
- size += r300_texture_get_stride(screen, tex, i) *
- r300_texture_get_nblocksy(tex, i);
- }
-
- size *= tex->b.b.depth0;
- tex->size = size;
- }
-}
-
-static void r300_setup_miptree(struct r300_screen* screen,
- struct r300_texture* tex)
-{
- struct pipe_resource* base = &tex->b.b;
- unsigned stride, size, layer_size, nblocksy, i;
- boolean rv350_mode = screen->caps.is_rv350;
-
- SCREEN_DBG(screen, DBG_TEXALLOC,
- "r300: Making miptree for texture, format %s\n",
- util_format_short_name(base->format));
-
- for (i = 0; i <= base->last_level; i++) {
- /* Let's see if this miplevel can be macrotiled. */
- tex->mip_macrotile[i] =
- (tex->macrotile == R300_BUFFER_TILED &&
- r300_texture_macro_switch(tex, i, rv350_mode, DIM_WIDTH) &&
- r300_texture_macro_switch(tex, i, rv350_mode, DIM_HEIGHT)) ?
- R300_BUFFER_TILED : R300_BUFFER_LINEAR;
-
- stride = r300_texture_get_stride(screen, tex, i);
- nblocksy = r300_texture_get_nblocksy(tex, i);
- layer_size = stride * nblocksy;
-
- if (base->nr_samples) {
- layer_size *= base->nr_samples;
- }
-
- if (base->target == PIPE_TEXTURE_CUBE)
- size = layer_size * 6;
- else
- size = layer_size * u_minify(base->depth0, i);
-
- tex->offset[i] = tex->size;
- tex->size = tex->offset[i] + size;
- tex->layer_size[i] = layer_size;
- tex->pitch[i] = stride / util_format_get_blocksize(base->format);
- tex->hwpitch[i] =
- tex->pitch[i] * util_format_get_blockwidth(base->format);
-
- SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d "
- "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n",
- i, u_minify(base->width0, i), u_minify(base->height0, i),
- u_minify(base->depth0, i), stride, tex->size,
- tex->mip_macrotile[i] ? "TRUE" : "FALSE");
- }
-}
-
-static void r300_setup_flags(struct r300_texture* tex)
-{
- tex->uses_pitch = !util_is_power_of_two(tex->b.b.width0) ||
- !util_is_power_of_two(tex->b.b.height0) ||
- tex->stride_override;
-}
-
-static void r300_setup_tiling(struct pipe_screen *screen,
- struct r300_texture *tex)
-{
- struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
- enum pipe_format format = tex->b.b.format;
- boolean rv350_mode = r300_screen(screen)->caps.is_rv350;
- boolean is_zb = util_format_is_depth_or_stencil(format);
- boolean dbg_no_tiling = SCREEN_DBG_ON(r300_screen(screen), DBG_NO_TILING);
-
- if (!util_format_is_plain(format)) {
- return;
- }
-
- /* If height == 1, disable microtiling except for zbuffer. */
- if (!is_zb && (tex->b.b.height0 == 1 || dbg_no_tiling)) {
- return;
- }
-
- /* Set microtiling. */
- switch (util_format_get_blocksize(format)) {
- case 1:
- case 4:
- tex->microtile = R300_BUFFER_TILED;
- break;
-
- case 2:
- case 8:
- if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) {
- tex->microtile = R300_BUFFER_SQUARETILED;
- }
- break;
- }
-
- if (dbg_no_tiling) {
- return;
- }
-
- /* Set macrotiling. */
- if (r300_texture_macro_switch(tex, 0, rv350_mode, DIM_WIDTH) &&
- r300_texture_macro_switch(tex, 0, rv350_mode, DIM_HEIGHT)) {
- tex->macrotile = R300_BUFFER_TILED;
- }
-}
-
static unsigned r300_texture_is_referenced(struct pipe_context *context,
struct pipe_resource *texture,
unsigned face, unsigned level)
@@ -920,8 +646,16 @@ static void r300_texture_destroy(struct pipe_screen *screen,
{
struct r300_texture* tex = (struct r300_texture*)texture;
struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys;
+ int i;
rws->buffer_reference(rws, &tex->buffer, NULL);
+ for (i = 0; i < R300_MAX_TEXTURE_LEVELS; i++) {
+ if (tex->hiz_mem[i])
+ u_mmFreeMem(tex->hiz_mem[i]);
+ if (tex->zmask_mem[i])
+ u_mmFreeMem(tex->zmask_mem[i]);
+ }
+
FREE(tex);
}
@@ -937,11 +671,10 @@ static boolean r300_texture_get_handle(struct pipe_screen* screen,
}
return rws->buffer_get_handle(rws, tex->buffer,
- r300_texture_get_stride(r300_screen(screen), tex, 0),
- whandle);
+ tex->desc.stride_in_bytes[0], whandle);
}
-struct u_resource_vtbl r300_texture_vtbl =
+struct u_resource_vtbl r300_texture_vtbl =
{
r300_texture_get_handle, /* get_handle */
r300_texture_destroy, /* resource_destroy */
@@ -954,17 +687,69 @@ struct u_resource_vtbl r300_texture_vtbl =
u_default_transfer_inline_write /* transfer_inline_write */
};
-/* Create a new texture. */
-struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
- const struct pipe_resource* base)
+/* The common texture constructor. */
+static struct r300_texture*
+r300_texture_create_object(struct r300_screen *rscreen,
+ const struct pipe_resource *base,
+ enum r300_buffer_tiling microtile,
+ enum r300_buffer_tiling macrotile,
+ unsigned stride_in_bytes_override,
+ unsigned max_buffer_size,
+ struct r300_winsys_buffer *buffer)
{
- struct r300_texture* tex = CALLOC_STRUCT(r300_texture);
- struct r300_screen* rscreen = r300_screen(screen);
- struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
-
+ struct r300_winsys_screen *rws = rscreen->rws;
+ struct r300_texture *tex = CALLOC_STRUCT(r300_texture);
if (!tex) {
+ if (buffer)
+ rws->buffer_reference(rws, &buffer, NULL);
+ return NULL;
+ }
+
+ /* Initialize the descriptor. */
+ if (!r300_texture_desc_init(rscreen, &tex->desc, base,
+ microtile, macrotile,
+ stride_in_bytes_override,
+ max_buffer_size)) {
+ if (buffer)
+ rws->buffer_reference(rws, &buffer, NULL);
+ FREE(tex);
return NULL;
}
+ /* Initialize the hardware state. */
+ r300_texture_setup_immutable_state(rscreen, tex);
+ r300_texture_setup_fb_state(rscreen, tex);
+
+ tex->desc.b.vtbl = &r300_texture_vtbl;
+ pipe_reference_init(&tex->desc.b.b.reference, 1);
+ tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ?
+ R300_DOMAIN_GTT :
+ R300_DOMAIN_VRAM | R300_DOMAIN_GTT;
+ tex->buffer = buffer;
+
+ /* Create the backing buffer if needed. */
+ if (!tex->buffer) {
+ tex->buffer = rws->buffer_create(rws, tex->desc.size_in_bytes, 2048,
+ base->bind, base->usage, tex->domain);
+
+ if (!tex->buffer) {
+ FREE(tex);
+ return NULL;
+ }
+ }
+
+ rws->buffer_set_tiling(rws, tex->buffer,
+ tex->desc.microtile, tex->desc.macrotile[0],
+ tex->desc.stride_in_bytes[0]);
+
+ return tex;
+}
+
+/* Create a new texture. */
+struct pipe_resource *r300_texture_create(struct pipe_screen *screen,
+ const struct pipe_resource *base)
+{
+ struct r300_screen *rscreen = r300_screen(screen);
+ enum r300_buffer_tiling microtile, macrotile;
/* Refuse to create a texture with size 0. */
if (!base->width0 ||
@@ -974,58 +759,70 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
fprintf(stderr, "r300: texture_create: "
"Got invalid texture dimensions: %ix%ix%i\n",
base->width0, base->height0, base->depth0);
- FREE(tex);
return NULL;
}
- tex->b.b = *base;
- tex->b.vtbl = &r300_texture_vtbl;
- pipe_reference_init(&tex->b.b.reference, 1);
- tex->b.b.screen = screen;
+ if ((base->flags & R300_RESOURCE_FLAG_TRANSFER) ||
+ (base->bind & PIPE_BIND_SCANOUT)) {
+ microtile = R300_BUFFER_LINEAR;
+ macrotile = R300_BUFFER_LINEAR;
+ } else {
+ microtile = R300_BUFFER_SELECT_LAYOUT;
+ macrotile = R300_BUFFER_SELECT_LAYOUT;
+ }
+
+ return (struct pipe_resource*)
+ r300_texture_create_object(rscreen, base, microtile, macrotile,
+ 0, 0, NULL);
+}
+
+struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen,
+ const struct pipe_resource *base,
+ struct winsys_handle *whandle)
+{
+ struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys;
+ struct r300_screen *rscreen = r300_screen(screen);
+ struct r300_winsys_buffer *buffer;
+ enum r300_buffer_tiling microtile, macrotile;
+ unsigned stride, size;
- r300_setup_flags(tex);
- if (!(base->flags & R300_RESOURCE_FLAG_TRANSFER) &&
- !(base->bind & PIPE_BIND_SCANOUT)) {
- r300_setup_tiling(screen, tex);
+ /* Support only 2D textures without mipmaps */
+ if (base->target != PIPE_TEXTURE_2D ||
+ base->depth0 != 1 ||
+ base->last_level != 0) {
+ return NULL;
}
- r300_setup_miptree(rscreen, tex);
- r300_texture_3d_fix_mipmapping(rscreen, tex);
- r300_texture_setup_immutable_state(rscreen, tex);
- r300_texture_setup_fb_state(rscreen, tex);
- SCREEN_DBG(rscreen, DBG_TEX,
- "r300: texture_create: Macro: %s, Micro: %s, Pitch: %i, "
- "Dim: %ix%ix%i, LastLevel: %i, Size: %i, Format: %s\n",
- tex->macrotile ? "YES" : " NO",
- tex->microtile ? "YES" : " NO",
- tex->hwpitch[0],
- base->width0, base->height0, base->depth0, base->last_level,
- tex->size,
- util_format_short_name(base->format));
+ buffer = rws->buffer_from_handle(rws, whandle, &stride, &size);
+ if (!buffer)
+ return NULL;
- tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ?
- R300_DOMAIN_GTT :
- R300_DOMAIN_VRAM | R300_DOMAIN_GTT;
+ rws->buffer_get_tiling(rws, buffer, &microtile, &macrotile);
- tex->buffer = rws->buffer_create(rws, tex->size, 2048, base->bind,
- base->usage, tex->domain);
+ /* Enforce a microtiled zbuffer. */
+ if (util_format_is_depth_or_stencil(base->format) &&
+ microtile == R300_BUFFER_LINEAR) {
+ switch (util_format_get_blocksize(base->format)) {
+ case 4:
+ microtile = R300_BUFFER_TILED;
+ break;
- if (!tex->buffer) {
- FREE(tex);
- return NULL;
+ case 2:
+ if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT))
+ microtile = R300_BUFFER_SQUARETILED;
+ break;
+ }
}
- rws->buffer_set_tiling(rws, tex->buffer,
- tex->microtile, tex->macrotile,
- tex->pitch[0] * util_format_get_blocksize(tex->b.b.format));
-
- return (struct pipe_resource*)tex;
+ return (struct pipe_resource*)
+ r300_texture_create_object(rscreen, base, microtile, macrotile,
+ stride, size, buffer);
}
/* Not required to implement u_resource_vtbl, consider moving to another file:
*/
struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
- struct pipe_resource* texture,
+ struct pipe_resource* texture,
unsigned face,
unsigned level,
unsigned zslice,
@@ -1035,7 +832,7 @@ struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
struct r300_surface* surface = CALLOC_STRUCT(r300_surface);
if (surface) {
- uint32_t stride, offset, tile_height;
+ uint32_t offset, tile_height;
pipe_reference_init(&surface->base.reference, 1);
pipe_resource_reference(&surface->base.texture, texture);
@@ -1054,23 +851,29 @@ struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
if (surface->domain & R300_DOMAIN_VRAM)
surface->domain &= ~R300_DOMAIN_GTT;
- surface->offset = r300_texture_get_offset(tex, level, zslice, face);
+ surface->offset = r300_texture_get_offset(&tex->desc,
+ level, zslice, face);
surface->pitch = tex->fb_state.pitch[level];
surface->format = tex->fb_state.format;
/* Parameters for the CBZB clear. */
+ surface->cbzb_allowed = tex->desc.cbzb_allowed[level];
surface->cbzb_width = align(surface->base.width, 64);
/* Height must be aligned to the size of a tile. */
- tile_height = r300_get_pixel_alignment(tex, tex->mip_macrotile[level],
+ tile_height = r300_get_pixel_alignment(tex->desc.b.b.format,
+ tex->desc.b.b.nr_samples,
+ tex->desc.microtile,
+ tex->desc.macrotile[level],
DIM_HEIGHT);
+
surface->cbzb_height = align((surface->base.height + 1) / 2,
tile_height);
/* Offset must be aligned to 2K and must point at the beginning
* of a scanline. */
- stride = r300_texture_get_stride(r300_screen(screen), tex, level);
- offset = surface->offset + stride * surface->cbzb_height;
+ offset = surface->offset +
+ tex->desc.stride_in_bytes[level] * surface->cbzb_height;
surface->cbzb_midpoint_offset = offset & ~2047;
surface->cbzb_pitch = surface->pitch & 0x1ffffc;
@@ -1080,11 +883,11 @@ struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
else
surface->cbzb_format = R300_DEPTHFORMAT_16BIT_INT_Z;
- SCREEN_DBG(r300_screen(screen), DBG_TEX,
+ SCREEN_DBG(r300_screen(screen), DBG_CBZB,
"CBZB Dim: %ix%i, Misalignment: %i, Macro: %s\n",
surface->cbzb_width, surface->cbzb_height,
offset & 2047,
- tex->mip_macrotile[level] ? "YES" : " NO");
+ tex->desc.macrotile[level] ? "YES" : " NO");
}
return &surface->base;
@@ -1097,88 +900,3 @@ void r300_tex_surface_destroy(struct pipe_surface* s)
pipe_resource_reference(&s->texture, NULL);
FREE(s);
}
-
-struct pipe_resource*
-r300_texture_from_handle(struct pipe_screen* screen,
- const struct pipe_resource* base,
- struct winsys_handle *whandle)
-{
- struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys;
- struct r300_screen* rscreen = r300_screen(screen);
- struct r300_winsys_buffer *buffer;
- struct r300_texture* tex;
- unsigned stride;
- boolean override_zb_flags;
-
- /* Support only 2D textures without mipmaps */
- if (base->target != PIPE_TEXTURE_2D ||
- base->depth0 != 1 ||
- base->last_level != 0) {
- return NULL;
- }
-
- buffer = rws->buffer_from_handle(rws, whandle, &stride);
- if (!buffer) {
- return NULL;
- }
-
- tex = CALLOC_STRUCT(r300_texture);
- if (!tex) {
- return NULL;
- }
-
- tex->b.b = *base;
- tex->b.vtbl = &r300_texture_vtbl;
- pipe_reference_init(&tex->b.b.reference, 1);
- tex->b.b.screen = screen;
- tex->domain = R300_DOMAIN_VRAM;
-
- tex->stride_override = stride;
-
- /* one ref already taken */
- tex->buffer = buffer;
-
- rws->buffer_get_tiling(rws, buffer, &tex->microtile, &tex->macrotile);
- r300_setup_flags(tex);
- SCREEN_DBG(rscreen, DBG_TEX,
- "r300: texture_from_handle: Macro: %s, Micro: %s, "
- "Pitch: % 4i, Dim: %ix%i, Format: %s\n",
- tex->macrotile ? "YES" : " NO",
- tex->microtile ? "YES" : " NO",
- stride / util_format_get_blocksize(base->format),
- base->width0, base->height0,
- util_format_short_name(base->format));
-
- /* Enforce microtiled zbuffer. */
- override_zb_flags = util_format_is_depth_or_stencil(base->format) &&
- tex->microtile == R300_BUFFER_LINEAR;
-
- if (override_zb_flags) {
- switch (util_format_get_blocksize(base->format)) {
- case 4:
- tex->microtile = R300_BUFFER_TILED;
- break;
-
- case 2:
- if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) {
- tex->microtile = R300_BUFFER_SQUARETILED;
- break;
- }
- /* Pass through. */
-
- default:
- override_zb_flags = FALSE;
- }
- }
-
- r300_setup_miptree(rscreen, tex);
- r300_texture_setup_immutable_state(rscreen, tex);
- r300_texture_setup_fb_state(rscreen, tex);
-
- if (override_zb_flags) {
- rws->buffer_set_tiling(rws, tex->buffer,
- tex->microtile, tex->macrotile,
- tex->pitch[0] * util_format_get_blocksize(tex->b.b.format));
- }
- return (struct pipe_resource*)tex;
-}
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index 99e7694254..a4524320fd 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -35,16 +35,11 @@ unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
const unsigned char *swizzle_view);
uint32_t r300_translate_texformat(enum pipe_format format,
- const unsigned char *swizzle_view);
+ const unsigned char *swizzle_view,
+ boolean is_r500);
uint32_t r500_tx_format_msb_bit(enum pipe_format format);
-unsigned r300_texture_get_stride(struct r300_screen* screen,
- struct r300_texture* tex, unsigned level);
-
-unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
- unsigned zslice, unsigned face);
-
void r300_texture_reinterpret_format(struct pipe_screen *screen,
struct pipe_resource *tex,
enum pipe_format new_format);
diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c
new file mode 100644
index 0000000000..5d690e8c33
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_texture_desc.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Copyright 2010 Marek Olšák <maraeo@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_texture_desc.h"
+
+#include "r300_context.h"
+#include "r300_winsys.h"
+
+#include "util/u_format.h"
+
+/* Returns the number of pixels that the texture should be aligned to
+ * in the given dimension. */
+unsigned r300_get_pixel_alignment(enum pipe_format format,
+ unsigned num_samples,
+ enum r300_buffer_tiling microtile,
+ enum r300_buffer_tiling macrotile,
+ enum r300_dim dim)
+{
+ static const unsigned table[2][5][3][2] =
+ {
+ {
+ /* Macro: linear linear linear
+ Micro: 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 */
+ },
+ {
+ /* Macro: tiled tiled tiled
+ Micro: linear tiled square-tiled */
+ {{256, 8}, {64, 32}, { 0, 0}}, /* 8 bits per pixel */
+ {{128, 8}, {64, 16}, {32, 32}}, /* 16 bits per pixel */
+ {{ 64, 8}, {32, 16}, { 0, 0}}, /* 32 bits per pixel */
+ {{ 32, 8}, { 0, 0}, {16, 16}}, /* 64 bits per pixel */
+ {{ 16, 8}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */
+ }
+ };
+ static const unsigned aa_block[2] = {4, 8};
+ unsigned tile = 0;
+ unsigned pixsize = util_format_get_blocksize(format);
+
+ assert(macrotile <= R300_BUFFER_TILED);
+ assert(microtile <= R300_BUFFER_SQUARETILED);
+ assert(pixsize <= 16);
+ assert(dim <= DIM_HEIGHT);
+
+ if (num_samples > 1) {
+ /* Multisampled textures have their own alignment scheme. */
+ if (pixsize == 4)
+ tile = aa_block[dim];
+ /* XXX FP16 AA. */
+ } else {
+ /* Standard alignment. */
+ tile = table[macrotile][util_logbase2(pixsize)][microtile][dim];
+ }
+
+ assert(tile);
+ return tile;
+}
+
+/* Return true if macrotiling should be enabled on the miplevel. */
+static boolean r300_texture_macro_switch(struct r300_texture_desc *desc,
+ unsigned level,
+ boolean rv350_mode,
+ enum r300_dim dim)
+{
+ unsigned tile, texdim;
+
+ tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples,
+ desc->microtile, R300_BUFFER_TILED, dim);
+ if (dim == DIM_WIDTH) {
+ texdim = u_minify(desc->b.b.width0, level);
+ } else {
+ texdim = u_minify(desc->b.b.height0, level);
+ }
+
+ /* See TX_FILTER1_n.MACRO_SWITCH. */
+ if (rv350_mode) {
+ return texdim >= tile;
+ } else {
+ return texdim > tile;
+ }
+}
+
+/**
+ * Return the stride, in bytes, of the texture image of the given texture
+ * at the given level.
+ */
+static unsigned r300_texture_get_stride(struct r300_screen *screen,
+ struct r300_texture_desc *desc,
+ unsigned level)
+{
+ unsigned tile_width, width, stride;
+
+ if (desc->stride_in_bytes_override)
+ return desc->stride_in_bytes_override;
+
+ /* Check the level. */
+ if (level > desc->b.b.last_level) {
+ SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n",
+ __FUNCTION__, level, desc->b.b.last_level);
+ return 0;
+ }
+
+ width = u_minify(desc->b.b.width0, level);
+
+ if (util_format_is_plain(desc->b.b.format)) {
+ tile_width = r300_get_pixel_alignment(desc->b.b.format,
+ desc->b.b.nr_samples,
+ desc->microtile,
+ desc->macrotile[level],
+ DIM_WIDTH);
+ width = align(width, tile_width);
+
+ stride = util_format_get_stride(desc->b.b.format, width);
+
+ /* Some IGPs need a minimum stride of 64 bytes, hmm... */
+ if (!desc->macrotile[level] &&
+ (screen->caps.family == CHIP_FAMILY_RS600 ||
+ screen->caps.family == CHIP_FAMILY_RS690 ||
+ screen->caps.family == CHIP_FAMILY_RS740)) {
+ unsigned min_stride;
+
+ if (desc->microtile) {
+ unsigned tile_height =
+ r300_get_pixel_alignment(desc->b.b.format,
+ desc->b.b.nr_samples,
+ desc->microtile,
+ desc->macrotile[level],
+ DIM_HEIGHT);
+
+ min_stride = 64 / tile_height;
+ } else {
+ min_stride = 64;
+ }
+
+ return stride < min_stride ? min_stride : stride;
+ }
+
+ /* The alignment to 32 bytes is sort of implied by the layout... */
+ return stride;
+ } else {
+ return align(util_format_get_stride(desc->b.b.format, width), 32);
+ }
+}
+
+static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc,
+ unsigned level,
+ boolean *out_aligned_for_cbzb)
+{
+ unsigned height, tile_height;
+
+ height = u_minify(desc->b.b.height0, level);
+
+ if (util_format_is_plain(desc->b.b.format)) {
+ tile_height = r300_get_pixel_alignment(desc->b.b.format,
+ desc->b.b.nr_samples,
+ desc->microtile,
+ desc->macrotile[level],
+ DIM_HEIGHT);
+ height = align(height, tile_height);
+
+ /* This is needed for the kernel checker, unfortunately. */
+ if ((desc->b.b.target != PIPE_TEXTURE_1D &&
+ desc->b.b.target != PIPE_TEXTURE_2D) ||
+ desc->b.b.last_level != 0) {
+ height = util_next_power_of_two(height);
+ }
+
+ /* See if the CBZB clear can be used on the buffer,
+ * taking the texture size into account. */
+ if (out_aligned_for_cbzb) {
+ if (desc->macrotile[level]) {
+ /* When clearing, the layer (width*height) is horizontally split
+ * into two, and the upper and lower halves are cleared by the CB
+ * and ZB units, respectively. Therefore, the number of macrotiles
+ * in the Y direction must be even. */
+
+ /* Align the height so that there is an even number of macrotiles.
+ * Do so for 3 or more macrotiles in the Y direction. */
+ if (level == 0 && desc->b.b.last_level == 0 &&
+ (desc->b.b.target == PIPE_TEXTURE_1D ||
+ desc->b.b.target == PIPE_TEXTURE_2D) &&
+ height >= tile_height * 3) {
+ height = align(height, tile_height * 2);
+ }
+
+ *out_aligned_for_cbzb = height % (tile_height * 2) == 0;
+ } else {
+ *out_aligned_for_cbzb = FALSE;
+ }
+ }
+ }
+
+ return util_format_get_nblocksy(desc->b.b.format, height);
+}
+
+static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen,
+ struct r300_texture_desc *desc)
+{
+ /* The kernels <= 2.6.34-rc4 compute the size of mipmapped 3D textures
+ * incorrectly. This is a workaround to prevent CS from being rejected. */
+
+ unsigned i, size;
+
+ if (!screen->rws->get_value(screen->rws, R300_VID_DRM_2_3_0) &&
+ desc->b.b.target == PIPE_TEXTURE_3D &&
+ desc->b.b.last_level > 0) {
+ size = 0;
+
+ for (i = 0; i <= desc->b.b.last_level; i++) {
+ size += desc->stride_in_bytes[i] *
+ r300_texture_get_nblocksy(desc, i, FALSE);
+ }
+
+ size *= desc->b.b.depth0;
+ desc->size_in_bytes = size;
+ }
+}
+
+/* Get a width in pixels from a stride in bytes. */
+static unsigned stride_to_width(enum pipe_format format,
+ unsigned stride_in_bytes)
+{
+ return (stride_in_bytes / util_format_get_blocksize(format)) *
+ util_format_get_blockwidth(format);
+}
+
+static void r300_setup_miptree(struct r300_screen *screen,
+ struct r300_texture_desc *desc,
+ boolean align_for_cbzb)
+{
+ struct pipe_resource *base = &desc->b.b;
+ unsigned stride, size, layer_size, nblocksy, i;
+ boolean rv350_mode = screen->caps.is_rv350;
+ boolean aligned_for_cbzb;
+
+ desc->size_in_bytes = 0;
+
+ SCREEN_DBG(screen, DBG_TEXALLOC,
+ "r300: Making miptree for texture, format %s\n",
+ util_format_short_name(base->format));
+
+ for (i = 0; i <= base->last_level; i++) {
+ /* Let's see if this miplevel can be macrotiled. */
+ desc->macrotile[i] =
+ (desc->macrotile[0] == R300_BUFFER_TILED &&
+ r300_texture_macro_switch(desc, i, rv350_mode, DIM_WIDTH) &&
+ r300_texture_macro_switch(desc, i, rv350_mode, DIM_HEIGHT)) ?
+ R300_BUFFER_TILED : R300_BUFFER_LINEAR;
+
+ stride = r300_texture_get_stride(screen, desc, i);
+
+ /* Compute the number of blocks in Y, see if the CBZB clear can be
+ * used on the texture. */
+ aligned_for_cbzb = FALSE;
+ if (align_for_cbzb && desc->cbzb_allowed[i])
+ nblocksy = r300_texture_get_nblocksy(desc, i, &aligned_for_cbzb);
+ else
+ nblocksy = r300_texture_get_nblocksy(desc, i, NULL);
+
+ layer_size = stride * nblocksy;
+
+ if (base->nr_samples) {
+ layer_size *= base->nr_samples;
+ }
+
+ if (base->target == PIPE_TEXTURE_CUBE)
+ size = layer_size * 6;
+ else
+ size = layer_size * u_minify(base->depth0, i);
+
+ desc->offset_in_bytes[i] = desc->size_in_bytes;
+ desc->size_in_bytes = desc->offset_in_bytes[i] + size;
+ desc->layer_size_in_bytes[i] = layer_size;
+ desc->stride_in_bytes[i] = stride;
+ desc->stride_in_pixels[i] = stride_to_width(desc->b.b.format, stride);
+ desc->cbzb_allowed[i] = desc->cbzb_allowed[i] && aligned_for_cbzb;
+
+ SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d "
+ "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n",
+ i, u_minify(base->width0, i), u_minify(base->height0, i),
+ u_minify(base->depth0, i), stride, desc->size_in_bytes,
+ desc->macrotile[i] ? "TRUE" : "FALSE");
+ }
+}
+
+static void r300_setup_flags(struct r300_texture_desc *desc)
+{
+ desc->uses_stride_addressing =
+ !util_is_power_of_two(desc->b.b.width0) ||
+ !util_is_power_of_two(desc->b.b.height0) ||
+ (desc->stride_in_bytes_override &&
+ stride_to_width(desc->b.b.format,
+ desc->stride_in_bytes_override) != desc->b.b.width0);
+
+ desc->is_npot =
+ desc->uses_stride_addressing ||
+ !util_is_power_of_two(desc->b.b.height0);
+}
+
+static void r300_setup_cbzb_flags(struct r300_screen *rscreen,
+ struct r300_texture_desc *desc)
+{
+ unsigned i, bpp;
+ boolean first_level_valid;
+
+ bpp = util_format_get_blocksizebits(desc->b.b.format);
+
+ /* 1) The texture must be point-sampled,
+ * 2) The depth must be 16 or 32 bits.
+ * 3) If the midpoint ZB offset is not aligned to 2048, it returns garbage
+ * with certain texture sizes. Macrotiling ensures the alignment. */
+ first_level_valid = desc->b.b.nr_samples <= 1 &&
+ (bpp == 16 || bpp == 32) &&
+ desc->macrotile[0];
+
+ for (i = 0; i <= desc->b.b.last_level; i++)
+ desc->cbzb_allowed[i] = first_level_valid && desc->macrotile[i];
+}
+
+static void r300_setup_tiling(struct r300_screen *screen,
+ struct r300_texture_desc *desc)
+{
+ struct r300_winsys_screen *rws = screen->rws;
+ enum pipe_format format = desc->b.b.format;
+ boolean rv350_mode = screen->caps.is_rv350;
+ boolean is_zb = util_format_is_depth_or_stencil(format);
+ boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING);
+
+ if (!util_format_is_plain(format)) {
+ return;
+ }
+
+ /* If height == 1, disable microtiling except for zbuffer. */
+ if (!is_zb && (desc->b.b.height0 == 1 || dbg_no_tiling)) {
+ return;
+ }
+
+ /* Set microtiling. */
+ switch (util_format_get_blocksize(format)) {
+ case 1:
+ case 4:
+ desc->microtile = R300_BUFFER_TILED;
+ break;
+
+ case 2:
+ case 8:
+ if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) {
+ desc->microtile = R300_BUFFER_SQUARETILED;
+ }
+ break;
+ }
+
+ if (dbg_no_tiling) {
+ return;
+ }
+
+ /* Set macrotiling. */
+ if (r300_texture_macro_switch(desc, 0, rv350_mode, DIM_WIDTH) &&
+ r300_texture_macro_switch(desc, 0, rv350_mode, DIM_HEIGHT)) {
+ desc->macrotile[0] = R300_BUFFER_TILED;
+ }
+}
+
+static void r300_tex_print_info(struct r300_screen *rscreen,
+ struct r300_texture_desc *desc,
+ const char *func)
+{
+ fprintf(stderr,
+ "r300: %s: Macro: %s, Micro: %s, Pitch: %i, Dim: %ix%ix%i, "
+ "LastLevel: %i, Size: %i, Format: %s\n",
+ func,
+ desc->macrotile[0] ? "YES" : " NO",
+ desc->microtile ? "YES" : " NO",
+ desc->stride_in_pixels[0],
+ desc->b.b.width0, desc->b.b.height0, desc->b.b.depth0,
+ desc->b.b.last_level, desc->size_in_bytes,
+ util_format_short_name(desc->b.b.format));
+}
+
+boolean r300_texture_desc_init(struct r300_screen *rscreen,
+ struct r300_texture_desc *desc,
+ const struct pipe_resource *base,
+ enum r300_buffer_tiling microtile,
+ enum r300_buffer_tiling macrotile,
+ unsigned stride_in_bytes_override,
+ unsigned max_buffer_size)
+{
+ desc->b.b = *base;
+ desc->b.b.screen = &rscreen->screen;
+
+ desc->stride_in_bytes_override = stride_in_bytes_override;
+
+ if (microtile == R300_BUFFER_SELECT_LAYOUT ||
+ macrotile == R300_BUFFER_SELECT_LAYOUT) {
+ r300_setup_tiling(rscreen, desc);
+ } else {
+ desc->microtile = microtile;
+ desc->macrotile[0] = macrotile;
+ assert(desc->b.b.last_level == 0);
+ }
+
+ r300_setup_flags(desc);
+ r300_setup_cbzb_flags(rscreen, desc);
+
+ /* Setup the miptree description. */
+ r300_setup_miptree(rscreen, desc, TRUE);
+ /* If the required buffer size is larger the given max size,
+ * try again without the alignment for the CBZB clear. */
+ if (max_buffer_size && desc->size_in_bytes > max_buffer_size) {
+ r300_setup_miptree(rscreen, desc, FALSE);
+ }
+
+ r300_texture_3d_fix_mipmapping(rscreen, desc);
+
+ if (max_buffer_size) {
+ /* Make sure the buffer we got is large enough. */
+ if (desc->size_in_bytes > max_buffer_size) {
+ fprintf(stderr, "r300: texture_from_handle: The buffer is not "
+ "large enough. Got: %i, Need: %i, Info:\n",
+ max_buffer_size, desc->size_in_bytes);
+ r300_tex_print_info(rscreen, desc, "texture_from_handle");
+ return FALSE;
+ }
+
+ desc->buffer_size_in_bytes = max_buffer_size;
+ } else {
+ desc->buffer_size_in_bytes = desc->size_in_bytes;
+ }
+
+ if (SCREEN_DBG_ON(rscreen, DBG_TEX))
+ r300_tex_print_info(rscreen, desc, "texture_from_handle");
+
+ return TRUE;
+}
+
+unsigned r300_texture_get_offset(struct r300_texture_desc *desc,
+ unsigned level, unsigned zslice,
+ unsigned face)
+{
+ unsigned offset = desc->offset_in_bytes[level];
+
+ switch (desc->b.b.target) {
+ case PIPE_TEXTURE_3D:
+ assert(face == 0);
+ return offset + zslice * desc->layer_size_in_bytes[level];
+
+ case PIPE_TEXTURE_CUBE:
+ assert(zslice == 0);
+ return offset + face * desc->layer_size_in_bytes[level];
+
+ default:
+ assert(zslice == 0 && face == 0);
+ return offset;
+ }
+}
diff --git a/src/gallium/drivers/r300/r300_texture_desc.h b/src/gallium/drivers/r300/r300_texture_desc.h
new file mode 100644
index 0000000000..95de66f654
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_texture_desc.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Copyright 2010 Marek Olšák <maraeo@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_TEXTURE_DESC_H
+#define R300_TEXTURE_DESC_H
+
+#include "r300_defines.h"
+
+struct pipe_resource;
+struct r300_screen;
+struct r300_texture_desc;
+struct r300_texture;
+
+enum r300_dim {
+ DIM_WIDTH = 0,
+ DIM_HEIGHT = 1
+};
+
+unsigned r300_get_pixel_alignment(enum pipe_format format,
+ unsigned num_samples,
+ enum r300_buffer_tiling microtile,
+ enum r300_buffer_tiling macrotile,
+ enum r300_dim dim);
+
+boolean r300_texture_desc_init(struct r300_screen *rscreen,
+ struct r300_texture_desc *desc,
+ const struct pipe_resource *base,
+ enum r300_buffer_tiling microtile,
+ enum r300_buffer_tiling macrotile,
+ unsigned stride_in_bytes_override,
+ unsigned max_buffer_size);
+
+unsigned r300_texture_get_offset(struct r300_texture_desc *desc,
+ unsigned level, unsigned zslice,
+ unsigned face);
+
+#endif
diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
index 51b2c55550..dd697b9c37 100644
--- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c
+++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
@@ -126,7 +126,7 @@ static unsigned translate_opcode(unsigned opcode)
/* case TGSI_OPCODE_SAD: return RC_OPCODE_SAD; */
/* case TGSI_OPCODE_TXF: return RC_OPCODE_TXF; */
/* case TGSI_OPCODE_TXQ: return RC_OPCODE_TXQ; */
- /* case TGSI_OPCODE_CONT: return RC_OPCODE_CONT; */
+ case TGSI_OPCODE_CONT: return RC_OPCODE_CONT;
/* case TGSI_OPCODE_EMIT: return RC_OPCODE_EMIT; */
/* case TGSI_OPCODE_ENDPRIM: return RC_OPCODE_ENDPRIM; */
/* case TGSI_OPCODE_BGNLOOP2: return RC_OPCODE_BGNLOOP2; */
diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c
index 3cc4c8c958..e9333b35ef 100644
--- a/src/gallium/drivers/r300/r300_transfer.c
+++ b/src/gallium/drivers/r300/r300_transfer.c
@@ -22,7 +22,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "r300_transfer.h"
-#include "r300_texture.h"
+#include "r300_texture_desc.h"
#include "r300_screen_buffer.h"
#include "util/u_memory.h"
@@ -35,8 +35,8 @@ struct r300_transfer {
/* Offset from start of buffer. */
unsigned offset;
- /* Detiled texture. */
- struct r300_texture *detiled_texture;
+ /* Linear texture. */
+ struct r300_texture *linear_texture;
};
/* Convenience cast wrapper. */
@@ -57,7 +57,7 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx,
subdst.face = 0;
subdst.level = 0;
- ctx->resource_copy_region(ctx, &r300transfer->detiled_texture->b.b, subdst,
+ ctx->resource_copy_region(ctx, &r300transfer->linear_texture->desc.b.b, subdst,
0, 0, 0,
tex, transfer->sr,
transfer->box.x, transfer->box.y, transfer->box.z,
@@ -77,7 +77,7 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx,
ctx->resource_copy_region(ctx, tex, transfer->sr,
transfer->box.x, transfer->box.y, transfer->box.z,
- &r300transfer->detiled_texture->b.b, subsrc,
+ &r300transfer->linear_texture->desc.b.b, subsrc,
0, 0, 0,
transfer->box.width, transfer->box.height);
@@ -93,7 +93,6 @@ r300_texture_get_transfer(struct pipe_context *ctx,
{
struct r300_context *r300 = r300_context(ctx);
struct r300_texture *tex = r300_texture(texture);
- struct r300_screen *r300screen = r300_screen(ctx->screen);
struct r300_transfer *trans;
struct pipe_resource base;
boolean referenced_cs, referenced_hw, blittable;
@@ -124,7 +123,7 @@ r300_texture_get_transfer(struct pipe_context *ctx,
/* If the texture is tiled, we must create a temporary detiled texture
* for this transfer.
* Also make write transfers pipelined. */
- if (tex->microtile || tex->macrotile ||
+ if (tex->desc.microtile || tex->desc.macrotile[sr.level] ||
((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) {
base.target = PIPE_TEXTURE_2D;
base.format = texture->format;
@@ -149,23 +148,23 @@ r300_texture_get_transfer(struct pipe_context *ctx,
}
/* Create the temporary texture. */
- trans->detiled_texture = r300_texture(
+ trans->linear_texture = r300_texture(
ctx->screen->resource_create(ctx->screen,
&base));
- if (!trans->detiled_texture) {
+ if (!trans->linear_texture) {
/* Oh crap, the thing can't create the texture.
* Let's flush and try again. */
ctx->flush(ctx, 0, NULL);
- trans->detiled_texture = r300_texture(
+ trans->linear_texture = r300_texture(
ctx->screen->resource_create(ctx->screen,
&base));
- if (!trans->detiled_texture) {
+ if (!trans->linear_texture) {
/* For linear textures, it's safe to fallback to
* an unpipelined transfer. */
- if (!tex->microtile && !tex->macrotile) {
+ if (!tex->desc.microtile && !tex->desc.macrotile[sr.level]) {
goto unpipelined;
}
@@ -177,8 +176,8 @@ r300_texture_get_transfer(struct pipe_context *ctx,
}
}
- assert(!trans->detiled_texture->microtile &&
- !trans->detiled_texture->macrotile);
+ assert(!trans->linear_texture->desc.microtile &&
+ !trans->linear_texture->desc.macrotile[0]);
/* Set the stride.
*
@@ -188,7 +187,7 @@ r300_texture_get_transfer(struct pipe_context *ctx,
* right thing internally.
*/
trans->transfer.stride =
- r300_texture_get_stride(r300screen, trans->detiled_texture, 0);
+ trans->linear_texture->desc.stride_in_bytes[0];
if (usage & PIPE_TRANSFER_READ) {
/* We cannot map a tiled texture directly because the data is
@@ -203,9 +202,9 @@ r300_texture_get_transfer(struct pipe_context *ctx,
unpipelined:
/* Unpipelined transfer. */
- trans->transfer.stride =
- r300_texture_get_stride(r300screen, tex, sr.level);
- trans->offset = r300_texture_get_offset(tex, sr.level, box->z, sr.face);
+ trans->transfer.stride = tex->desc.stride_in_bytes[sr.level];
+ trans->offset = r300_texture_get_offset(&tex->desc,
+ sr.level, box->z, sr.face);
if (referenced_cs)
ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
@@ -219,13 +218,13 @@ void r300_texture_transfer_destroy(struct pipe_context *ctx,
{
struct r300_transfer *r300transfer = r300_transfer(trans);
- if (r300transfer->detiled_texture) {
+ if (r300transfer->linear_texture) {
if (trans->usage & PIPE_TRANSFER_WRITE) {
r300_copy_into_tiled_texture(ctx, r300transfer);
}
pipe_resource_reference(
- (struct pipe_resource**)&r300transfer->detiled_texture, NULL);
+ (struct pipe_resource**)&r300transfer->linear_texture, NULL);
}
pipe_resource_reference(&trans->resource, NULL);
FREE(trans);
@@ -239,13 +238,13 @@ void* r300_texture_transfer_map(struct pipe_context *ctx,
struct r300_transfer *r300transfer = r300_transfer(transfer);
struct r300_texture *tex = r300_texture(transfer->resource);
char *map;
- enum pipe_format format = tex->b.b.format;
+ enum pipe_format format = tex->desc.b.b.format;
- if (r300transfer->detiled_texture) {
+ if (r300transfer->linear_texture) {
/* The detiled texture is of the same size as the region being mapped
* (no offset needed). */
return rws->buffer_map(rws,
- r300transfer->detiled_texture->buffer,
+ r300transfer->linear_texture->buffer,
r300->cs,
transfer->usage);
} else {
@@ -270,8 +269,8 @@ void r300_texture_transfer_unmap(struct pipe_context *ctx,
struct r300_transfer *r300transfer = r300_transfer(transfer);
struct r300_texture *tex = r300_texture(transfer->resource);
- if (r300transfer->detiled_texture) {
- rws->buffer_unmap(rws, r300transfer->detiled_texture->buffer);
+ if (r300transfer->linear_texture) {
+ rws->buffer_unmap(rws, r300transfer->linear_texture->buffer);
} else {
rws->buffer_unmap(rws, tex->buffer);
}
diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c
index b25c786d6b..54c8de1241 100644
--- a/src/gallium/drivers/r300/r300_vs.c
+++ b/src/gallium/drivers/r300/r300_vs.c
@@ -207,7 +207,7 @@ void r300_translate_vertex_shader(struct r300_context *r300,
compiler.Base.max_temp_regs = 32;
if (compiler.Base.Debug) {
- debug_printf("r300: Initial vertex program\n");
+ DBG(r300, DBG_VP, "r300: Initial vertex program\n");
tgsi_dump(vs->state.tokens, 0);
}
@@ -227,8 +227,7 @@ void r300_translate_vertex_shader(struct r300_context *r300,
/* Invoke the compiler */
r3xx_compile_vertex_program(&compiler);
if (compiler.Base.Error) {
- /* XXX We should fallback using Draw. */
- fprintf(stderr, "r300 VP: Compiler error:\n%sUsing a dummy shader"
+ DBG(r300, DBG_VP, "r300 VP: Compiler error:\n%sUsing a dummy shader"
" instead.\nIf there's an 'unknown opcode' message, please"
" file a bug report and attach this log.\n", compiler.Base.ErrorMsg);
diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h
index 7e115c2d62..187780750f 100644
--- a/src/gallium/drivers/r300/r300_winsys.h
+++ b/src/gallium/drivers/r300/r300_winsys.h
@@ -49,6 +49,8 @@ enum r300_value_id {
R300_VID_Z_PIPES,
R300_VID_SQUARE_TILING_SUPPORT,
R300_VID_DRM_2_3_0,
+ R300_VID_DRM_2_6_0,
+ R300_CAN_HYPERZ,
};
enum r300_reference_domain { /* bitfield */
@@ -184,12 +186,13 @@ struct r300_winsys_screen {
* \param ws The winsys this function is called from.
* \param whandle A winsys handle pointer as was received from a state
* tracker.
- * \param stride A pointer to the stride return variable.
- * The stride is in bytes.
+ * \param stride The returned buffer stride in bytes.
+ * \param size The returned buffer size.
*/
struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *ws,
struct winsys_handle *whandle,
- unsigned *stride);
+ unsigned *stride,
+ unsigned *size);
/**
* Get a winsys handle from a winsys buffer. The internal structure
diff --git a/src/gallium/drivers/r600/Makefile b/src/gallium/drivers/r600/Makefile
index aae31a6a6e..fc94ae71f4 100644
--- a/src/gallium/drivers/r600/Makefile
+++ b/src/gallium/drivers/r600/Makefile
@@ -9,6 +9,7 @@ LIBRARY_INCLUDES = \
C_SOURCES = \
r600_buffer.c \
r600_context.c \
+ r600_shader.c \
r600_draw.c \
r600_blit.c \
r600_helper.c \
@@ -17,11 +18,7 @@ C_SOURCES = \
r600_screen.c \
r600_state.c \
r600_texture.c \
- r600_shader.c \
- r600_compiler.c \
- r600_compiler_tgsi.c \
- r600_compiler_dump.c \
- r600_compiler_r600.c \
- r600_compiler_r700.c
+ r600_asm.c \
+ r700_asm.c
include ../../Makefile.template
diff --git a/src/gallium/drivers/r600/SConscript b/src/gallium/drivers/r600/SConscript
index 26e2f1941c..99c8644e02 100644
--- a/src/gallium/drivers/r600/SConscript
+++ b/src/gallium/drivers/r600/SConscript
@@ -27,11 +27,8 @@ r600 = env.ConvenienceLibrary(
'r600_state.c',
'r600_texture.c',
'r600_shader.c',
- 'r600_compiler.c',
- 'r600_compiler_tgsi.c',
- 'r600_compiler_dump.c',
- 'r600_compiler_r600.c',
- 'r600_compiler_r700.c'
+ 'r600_asm.c',
+ 'r700_asm.c',
])
Export('r600')
diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c
new file mode 100644
index 0000000000..9ea9d4354d
--- /dev/null
+++ b/src/gallium/drivers/r600/r600_asm.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright 2010 Jerome Glisse <glisse@freedesktop.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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "r600_asm.h"
+#include "r600_context.h"
+#include "util/u_memory.h"
+#include "r600_sq.h"
+#include <stdio.h>
+#include <errno.h>
+
+int r700_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id);
+
+static struct r600_bc_cf *r600_bc_cf(void)
+{
+ struct r600_bc_cf *cf = CALLOC_STRUCT(r600_bc_cf);
+
+ if (cf == NULL)
+ return NULL;
+ LIST_INITHEAD(&cf->list);
+ LIST_INITHEAD(&cf->alu);
+ LIST_INITHEAD(&cf->vtx);
+ LIST_INITHEAD(&cf->tex);
+ return cf;
+}
+
+static struct r600_bc_alu *r600_bc_alu(void)
+{
+ struct r600_bc_alu *alu = CALLOC_STRUCT(r600_bc_alu);
+
+ if (alu == NULL)
+ return NULL;
+ LIST_INITHEAD(&alu->list);
+ return alu;
+}
+
+static struct r600_bc_vtx *r600_bc_vtx(void)
+{
+ struct r600_bc_vtx *vtx = CALLOC_STRUCT(r600_bc_vtx);
+
+ if (vtx == NULL)
+ return NULL;
+ LIST_INITHEAD(&vtx->list);
+ return vtx;
+}
+
+static struct r600_bc_tex *r600_bc_tex(void)
+{
+ struct r600_bc_tex *tex = CALLOC_STRUCT(r600_bc_tex);
+
+ if (tex == NULL)
+ return NULL;
+ LIST_INITHEAD(&tex->list);
+ return tex;
+}
+
+int r600_bc_init(struct r600_bc *bc, enum radeon_family family)
+{
+ LIST_INITHEAD(&bc->cf);
+ bc->family = family;
+ return 0;
+}
+
+static int r600_bc_add_cf(struct r600_bc *bc)
+{
+ struct r600_bc_cf *cf = r600_bc_cf();
+
+ if (cf == NULL)
+ return -ENOMEM;
+ LIST_ADDTAIL(&cf->list, &bc->cf);
+ if (bc->cf_last)
+ cf->id = bc->cf_last->id + 2;
+ bc->cf_last = cf;
+ bc->ncf++;
+ bc->ndw += 2;
+ bc->force_add_cf = 0;
+ return 0;
+}
+
+int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output)
+{
+ int r;
+
+ r = r600_bc_add_cf(bc);
+ if (r)
+ return r;
+ bc->cf_last->inst = output->inst;
+ memcpy(&bc->cf_last->output, output, sizeof(struct r600_bc_output));
+ return 0;
+}
+
+int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu)
+{
+ struct r600_bc_alu *nalu = r600_bc_alu();
+ struct r600_bc_alu *lalu;
+ int i, r;
+
+ if (nalu == NULL)
+ return -ENOMEM;
+ memcpy(nalu, alu, sizeof(struct r600_bc_alu));
+ nalu->nliteral = 0;
+
+ /* cf can contains only alu or only vtx or only tex */
+ if (bc->cf_last == NULL || bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3) ||
+ bc->force_add_cf) {
+ /* at most 128 slots, one add alu can add 4 slots + 4 constant worst case */
+ r = r600_bc_add_cf(bc);
+ if (r) {
+ free(nalu);
+ return r;
+ }
+ bc->cf_last->inst = V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3;
+ }
+ if (alu->last && (bc->cf_last->ndw >> 1) >= 124) {
+ bc->force_add_cf = 1;
+ }
+ /* number of gpr == the last gpr used in any alu */
+ for (i = 0; i < 3; i++) {
+ if (alu->src[i].sel >= bc->ngpr && alu->src[i].sel < 128) {
+ bc->ngpr = alu->src[i].sel + 1;
+ }
+ /* compute how many literal are needed
+ * either 2 or 4 literals
+ */
+ if (alu->src[i].sel == 253) {
+ if (((alu->src[i].chan + 2) & 0x6) > nalu->nliteral) {
+ nalu->nliteral = (alu->src[i].chan + 2) & 0x6;
+ }
+ }
+ }
+ if (!LIST_IS_EMPTY(&bc->cf_last->alu)) {
+ lalu = LIST_ENTRY(struct r600_bc_alu, bc->cf_last->alu.prev, list);
+ if (!lalu->last && lalu->nliteral > nalu->nliteral) {
+ nalu->nliteral = lalu->nliteral;
+ }
+ }
+ if (alu->dst.sel >= bc->ngpr) {
+ bc->ngpr = alu->dst.sel + 1;
+ }
+ LIST_ADDTAIL(&nalu->list, &bc->cf_last->alu);
+ /* each alu use 2 dwords */
+ bc->cf_last->ndw += 2;
+ bc->ndw += 2;
+ return 0;
+}
+
+int r600_bc_add_literal(struct r600_bc *bc, const u32 *value)
+{
+ struct r600_bc_alu *alu;
+
+ if (bc->cf_last == NULL) {
+ return 0;
+ }
+ if (bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_TEX) {
+ return 0;
+ }
+ if (bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3) ||
+ LIST_IS_EMPTY(&bc->cf_last->alu)) {
+ R600_ERR("last CF is not ALU (%p)\n", bc->cf_last);
+ return -EINVAL;
+ }
+ alu = LIST_ENTRY(struct r600_bc_alu, bc->cf_last->alu.prev, list);
+ if (!alu->last || !alu->nliteral || alu->literal_added) {
+ return 0;
+ }
+ memcpy(alu->value, value, 4 * 4);
+ bc->cf_last->ndw += alu->nliteral;
+ bc->ndw += alu->nliteral;
+ alu->literal_added = 1;
+ return 0;
+}
+
+int r600_bc_add_vtx(struct r600_bc *bc, const struct r600_bc_vtx *vtx)
+{
+ struct r600_bc_vtx *nvtx = r600_bc_vtx();
+ int r;
+
+ if (nvtx == NULL)
+ return -ENOMEM;
+ memcpy(nvtx, vtx, sizeof(struct r600_bc_vtx));
+
+ /* cf can contains only alu or only vtx or only tex */
+ if (bc->cf_last == NULL ||
+ (bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_VTX &&
+ bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC)) {
+ r = r600_bc_add_cf(bc);
+ if (r) {
+ free(nvtx);
+ return r;
+ }
+ bc->cf_last->inst = V_SQ_CF_WORD1_SQ_CF_INST_VTX;
+ }
+ LIST_ADDTAIL(&nvtx->list, &bc->cf_last->vtx);
+ /* each fetch use 4 dwords */
+ bc->cf_last->ndw += 4;
+ bc->ndw += 4;
+ return 0;
+}
+
+int r600_bc_add_tex(struct r600_bc *bc, const struct r600_bc_tex *tex)
+{
+ struct r600_bc_tex *ntex = r600_bc_tex();
+ int r;
+
+ if (ntex == NULL)
+ return -ENOMEM;
+ memcpy(ntex, tex, sizeof(struct r600_bc_tex));
+
+ /* cf can contains only alu or only vtx or only tex */
+ if (bc->cf_last == NULL ||
+ bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_TEX) {
+ r = r600_bc_add_cf(bc);
+ if (r) {
+ free(ntex);
+ return r;
+ }
+ bc->cf_last->inst = V_SQ_CF_WORD1_SQ_CF_INST_TEX;
+ }
+ LIST_ADDTAIL(&ntex->list, &bc->cf_last->tex);
+ /* each texture fetch use 4 dwords */
+ bc->cf_last->ndw += 4;
+ bc->ndw += 4;
+ return 0;
+}
+
+static int r600_bc_vtx_build(struct r600_bc *bc, struct r600_bc_vtx *vtx, unsigned id)
+{
+ bc->bytecode[id++] = S_SQ_VTX_WORD0_BUFFER_ID(vtx->buffer_id) |
+ S_SQ_VTX_WORD0_SRC_GPR(vtx->src_gpr) |
+ S_SQ_VTX_WORD0_SRC_SEL_X(vtx->src_sel_x) |
+ S_SQ_VTX_WORD0_MEGA_FETCH_COUNT(vtx->mega_fetch_count);
+ bc->bytecode[id++] = S_SQ_VTX_WORD1_DST_SEL_X(vtx->dst_sel_x) |
+ S_SQ_VTX_WORD1_DST_SEL_Y(vtx->dst_sel_y) |
+ S_SQ_VTX_WORD1_DST_SEL_Z(vtx->dst_sel_z) |
+ S_SQ_VTX_WORD1_DST_SEL_W(vtx->dst_sel_w) |
+ S_SQ_VTX_WORD1_USE_CONST_FIELDS(1) |
+ S_SQ_VTX_WORD1_GPR_DST_GPR(vtx->dst_gpr);
+ bc->bytecode[id++] = S_SQ_VTX_WORD2_MEGA_FETCH(1);
+ bc->bytecode[id++] = 0;
+ return 0;
+}
+
+static int r600_bc_tex_build(struct r600_bc *bc, struct r600_bc_tex *tex, unsigned id)
+{
+ bc->bytecode[id++] = S_SQ_TEX_WORD0_TEX_INST(tex->inst) |
+ S_SQ_TEX_WORD0_RESOURCE_ID(tex->resource_id) |
+ S_SQ_TEX_WORD0_SRC_GPR(tex->src_gpr) |
+ S_SQ_TEX_WORD0_SRC_REL(tex->src_rel);
+ bc->bytecode[id++] = S_SQ_TEX_WORD1_DST_GPR(tex->dst_gpr) |
+ S_SQ_TEX_WORD1_DST_REL(tex->dst_rel) |
+ S_SQ_TEX_WORD1_DST_SEL_X(tex->dst_sel_x) |
+ S_SQ_TEX_WORD1_DST_SEL_Y(tex->dst_sel_y) |
+ S_SQ_TEX_WORD1_DST_SEL_Z(tex->dst_sel_z) |
+ S_SQ_TEX_WORD1_DST_SEL_W(tex->dst_sel_w) |
+ S_SQ_TEX_WORD1_LOD_BIAS(tex->lod_bias) |
+ S_SQ_TEX_WORD1_COORD_TYPE_X(tex->coord_type_x) |
+ S_SQ_TEX_WORD1_COORD_TYPE_Y(tex->coord_type_y) |
+ S_SQ_TEX_WORD1_COORD_TYPE_Z(tex->coord_type_z) |
+ S_SQ_TEX_WORD1_COORD_TYPE_W(tex->coord_type_w);
+ bc->bytecode[id++] = S_SQ_TEX_WORD2_OFFSET_X(tex->offset_x) |
+ S_SQ_TEX_WORD2_OFFSET_Y(tex->offset_y) |
+ S_SQ_TEX_WORD2_OFFSET_Z(tex->offset_z) |
+ S_SQ_TEX_WORD2_SAMPLER_ID(tex->sampler_id) |
+ S_SQ_TEX_WORD2_SRC_SEL_X(tex->src_sel_x) |
+ S_SQ_TEX_WORD2_SRC_SEL_Y(tex->src_sel_y) |
+ S_SQ_TEX_WORD2_SRC_SEL_Z(tex->src_sel_z) |
+ S_SQ_TEX_WORD2_SRC_SEL_W(tex->src_sel_w);
+ bc->bytecode[id++] = 0;
+ return 0;
+}
+
+static int r600_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id)
+{
+ unsigned i;
+
+ /* don't replace gpr by pv or ps for destination register */
+ if (alu->is_op3) {
+ bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
+ S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
+ S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
+ S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
+ S_SQ_ALU_WORD0_LAST(alu->last);
+ bc->bytecode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
+ S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
+ S_SQ_ALU_WORD1_CLAMP(alu->dst.clamp) |
+ S_SQ_ALU_WORD1_OP3_SRC2_SEL(alu->src[2].sel) |
+ S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) |
+ S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) |
+ S_SQ_ALU_WORD1_OP3_ALU_INST(alu->inst) |
+ S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
+ } else {
+ bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
+ S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
+ S_SQ_ALU_WORD0_SRC0_NEG(alu->src[0].neg) |
+ S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
+ S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
+ S_SQ_ALU_WORD0_SRC1_NEG(alu->src[1].neg) |
+ S_SQ_ALU_WORD0_LAST(alu->last);
+ bc->bytecode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
+ S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
+ S_SQ_ALU_WORD1_CLAMP(alu->dst.clamp) |
+ S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) |
+ S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) |
+ S_SQ_ALU_WORD1_OP2_WRITE_MASK(alu->dst.write) |
+ S_SQ_ALU_WORD1_OP2_ALU_INST(alu->inst) |
+ S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
+ }
+ if (alu->last) {
+ for (i = 0; i < alu->nliteral; i++) {
+ bc->bytecode[id++] = alu->value[i];
+ }
+ }
+ return 0;
+}
+
+static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf)
+{
+ unsigned id = cf->id;
+
+ switch (cf->inst) {
+ case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
+ bc->bytecode[id++] = S_SQ_CF_ALU_WORD0_ADDR(cf->addr >> 1);
+ bc->bytecode[id++] = S_SQ_CF_ALU_WORD1_CF_INST(cf->inst >> 3) |
+ S_SQ_CF_ALU_WORD1_BARRIER(1) |
+ S_SQ_CF_ALU_WORD1_COUNT((cf->ndw / 2) - 1);
+ break;
+ case V_SQ_CF_WORD1_SQ_CF_INST_TEX:
+ case V_SQ_CF_WORD1_SQ_CF_INST_VTX:
+ case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC:
+ bc->bytecode[id++] = S_SQ_CF_WORD0_ADDR(cf->addr >> 1);
+ bc->bytecode[id++] = S_SQ_CF_WORD1_CF_INST(cf->inst) |
+ S_SQ_CF_WORD1_BARRIER(1) |
+ S_SQ_CF_WORD1_COUNT((cf->ndw / 4) - 1);
+ break;
+ case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
+ case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
+ bc->bytecode[id++] = S_SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR(cf->output.gpr) |
+ S_SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE(cf->output.elem_size) |
+ S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(cf->output.array_base) |
+ S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(cf->output.type);
+ bc->bytecode[id++] = S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X(cf->output.swizzle_x) |
+ S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y(cf->output.swizzle_y) |
+ S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z(cf->output.swizzle_z) |
+ S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W(cf->output.swizzle_w) |
+ S_SQ_CF_ALLOC_EXPORT_WORD1_BARRIER(cf->output.barrier) |
+ S_SQ_CF_ALLOC_EXPORT_WORD1_CF_INST(cf->output.inst) |
+ S_SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM(cf->output.end_of_program);
+ break;
+ default:
+ R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int r600_bc_build(struct r600_bc *bc)
+{
+ struct r600_bc_cf *cf;
+ struct r600_bc_alu *alu;
+ struct r600_bc_vtx *vtx;
+ struct r600_bc_tex *tex;
+ unsigned addr;
+ int r;
+
+
+ /* first path compute addr of each CF block */
+ /* addr start after all the CF instructions */
+ addr = bc->cf_last->id + 2;
+ LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) {
+ switch (cf->inst) {
+ case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
+ break;
+ case V_SQ_CF_WORD1_SQ_CF_INST_TEX:
+ case V_SQ_CF_WORD1_SQ_CF_INST_VTX:
+ case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC:
+ /* fetch node need to be 16 bytes aligned*/
+ addr += 3;
+ addr &= 0xFFFFFFFCUL;
+ break;
+ case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
+ case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
+ break;
+ default:
+ R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst);
+ return -EINVAL;
+ }
+ cf->addr = addr;
+ addr += cf->ndw;
+ bc->ndw = cf->addr + cf->ndw;
+ }
+ free(bc->bytecode);
+ bc->bytecode = calloc(1, bc->ndw * 4);
+ if (bc->bytecode == NULL)
+ return -ENOMEM;
+ LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) {
+ addr = cf->addr;
+ r = r600_bc_cf_build(bc, cf);
+ if (r)
+ return r;
+ switch (cf->inst) {
+ case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
+ LIST_FOR_EACH_ENTRY(alu, &cf->alu, list) {
+ switch (bc->family) {
+ case CHIP_R600:
+ case CHIP_RV610:
+ case CHIP_RV630:
+ case CHIP_RV670:
+ case CHIP_RV620:
+ case CHIP_RV635:
+ case CHIP_RS780:
+ case CHIP_RS880:
+ r = r600_bc_alu_build(bc, alu, addr);
+ break;
+ case CHIP_RV770:
+ case CHIP_RV730:
+ case CHIP_RV710:
+ case CHIP_RV740:
+ r = r700_bc_alu_build(bc, alu, addr);
+ break;
+ default:
+ R600_ERR("unknown family %d\n", bc->family);
+ return -EINVAL;
+ }
+ if (r)
+ return r;
+ addr += 2;
+ if (alu->last) {
+ addr += alu->nliteral;
+ }
+ }
+ break;
+ case V_SQ_CF_WORD1_SQ_CF_INST_VTX:
+ case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC:
+ LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) {
+ r = r600_bc_vtx_build(bc, vtx, addr);
+ if (r)
+ return r;
+ addr += 4;
+ }
+ break;
+ case V_SQ_CF_WORD1_SQ_CF_INST_TEX:
+ LIST_FOR_EACH_ENTRY(tex, &cf->tex, list) {
+ r = r600_bc_tex_build(bc, tex, addr);
+ if (r)
+ return r;
+ addr += 4;
+ }
+ break;
+ case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
+ case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
+ break;
+ default:
+ R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
diff --git a/src/gallium/drivers/r600/r600_asm.h b/src/gallium/drivers/r600/r600_asm.h
new file mode 100644
index 0000000000..10d98afaf0
--- /dev/null
+++ b/src/gallium/drivers/r600/r600_asm.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2010 Jerome Glisse <glisse@freedesktop.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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef R600_ASM_H
+#define R600_ASM_H
+
+#include "radeon.h"
+#include "util/u_double_list.h"
+
+struct r600_bc_alu_src {
+ unsigned sel;
+ unsigned chan;
+ unsigned neg;
+ unsigned abs;
+};
+
+struct r600_bc_alu_dst {
+ unsigned sel;
+ unsigned chan;
+ unsigned clamp;
+ unsigned write;
+};
+
+struct r600_bc_alu {
+ struct list_head list;
+ struct r600_bc_alu_src src[3];
+ struct r600_bc_alu_dst dst;
+ unsigned inst;
+ unsigned last;
+ unsigned is_op3;
+ unsigned nliteral;
+ unsigned literal_added;
+ u32 value[4];
+};
+
+struct r600_bc_tex {
+ struct list_head list;
+ unsigned inst;
+ unsigned resource_id;
+ unsigned src_gpr;
+ unsigned src_rel;
+ unsigned dst_gpr;
+ unsigned dst_rel;
+ unsigned dst_sel_x;
+ unsigned dst_sel_y;
+ unsigned dst_sel_z;
+ unsigned dst_sel_w;
+ unsigned lod_bias;
+ unsigned coord_type_x;
+ unsigned coord_type_y;
+ unsigned coord_type_z;
+ unsigned coord_type_w;
+ unsigned offset_x;
+ unsigned offset_y;
+ unsigned offset_z;
+ unsigned sampler_id;
+ unsigned src_sel_x;
+ unsigned src_sel_y;
+ unsigned src_sel_z;
+ unsigned src_sel_w;
+};
+
+struct r600_bc_vtx {
+ struct list_head list;
+ unsigned inst;
+ unsigned fetch_type;
+ unsigned buffer_id;
+ unsigned src_gpr;
+ unsigned src_sel_x;
+ unsigned mega_fetch_count;
+ unsigned dst_gpr;
+ unsigned dst_sel_x;
+ unsigned dst_sel_y;
+ unsigned dst_sel_z;
+ unsigned dst_sel_w;
+};
+
+struct r600_bc_output {
+ unsigned array_base;
+ unsigned type;
+ unsigned end_of_program;
+ unsigned inst;
+ unsigned elem_size;
+ unsigned gpr;
+ unsigned swizzle_x;
+ unsigned swizzle_y;
+ unsigned swizzle_z;
+ unsigned swizzle_w;
+ unsigned barrier;
+};
+
+struct r600_bc_cf {
+ struct list_head list;
+ unsigned inst;
+ unsigned addr;
+ unsigned ndw;
+ unsigned id;
+ struct list_head alu;
+ struct list_head tex;
+ struct list_head vtx;
+ struct r600_bc_output output;
+};
+
+struct r600_bc {
+ enum radeon_family family;
+ struct list_head cf;
+ struct r600_bc_cf *cf_last;
+ unsigned ndw;
+ unsigned ncf;
+ unsigned ngpr;
+ unsigned nresource;
+ unsigned force_add_cf;
+ u32 *bytecode;
+};
+
+int r600_bc_init(struct r600_bc *bc, enum radeon_family family);
+int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu);
+int r600_bc_add_literal(struct r600_bc *bc, const u32 *value);
+int r600_bc_add_vtx(struct r600_bc *bc, const struct r600_bc_vtx *vtx);
+int r600_bc_add_tex(struct r600_bc *bc, const struct r600_bc_tex *tex);
+int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output);
+int r600_bc_build(struct r600_bc *bc);
+
+#endif
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index 1dcb19babc..f4eedfe4cb 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -34,31 +34,37 @@
static void r600_blitter_save_states(struct r600_context *rctx)
{
- util_blitter_save_blend(rctx->blitter,
- rctx->draw->state[R600_BLEND]);
- util_blitter_save_depth_stencil_alpha(rctx->blitter,
- rctx->draw->state[R600_DSA]);
- util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref);
- util_blitter_save_rasterizer(rctx->blitter,
- rctx->draw->state[R600_RASTERIZER]);
- util_blitter_save_fragment_shader(rctx->blitter,
- rctx->ps_shader);
- util_blitter_save_vertex_shader(rctx->blitter,
- rctx->vs_shader);
- util_blitter_save_vertex_elements(rctx->blitter,
- rctx->vertex_elements);
- util_blitter_save_viewport(rctx->blitter,
- &rctx->viewport);
+ util_blitter_save_blend(rctx->blitter, rctx->blend);
+ util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->dsa);
+ if (rctx->stencil_ref) {
+ util_blitter_save_stencil_ref(rctx->blitter,
+ &rctx->stencil_ref->state.stencil_ref);
+ }
+ util_blitter_save_rasterizer(rctx->blitter, rctx->rasterizer);
+ util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader);
+ util_blitter_save_vertex_shader(rctx->blitter, rctx->vs_shader);
+ util_blitter_save_vertex_elements(rctx->blitter, rctx->vertex_elements);
+ if (rctx->viewport) {
+ util_blitter_save_viewport(rctx->blitter, &rctx->viewport->state.viewport);
+ }
/* XXX util_blitter_save_clip(rctx->blitter, &rctx->clip); */
util_blitter_save_vertex_buffers(rctx->blitter, rctx->nvertex_buffer,
- rctx->vertex_buffer);
+ rctx->vertex_buffer);
+
+ /* remove ptr so they don't get deleted */
+ rctx->blend = NULL;
+ rctx->vs_shader = NULL;
+ rctx->ps_shader = NULL;
+ rctx->rasterizer = NULL;
+ rctx->dsa = NULL;
+ rctx->vertex_elements = NULL;
}
static void r600_clear(struct pipe_context *ctx, unsigned buffers,
const float *rgba, double depth, unsigned stencil)
{
struct r600_context *rctx = r600_context(ctx);
- struct pipe_framebuffer_state *fb = &rctx->fb_state;
+ struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
r600_blitter_save_states(rctx);
util_blitter_clear(rctx->blitter, fb->width, fb->height,
@@ -73,9 +79,10 @@ static void r600_clear_render_target(struct pipe_context *pipe,
unsigned width, unsigned height)
{
struct r600_context *rctx = r600_context(pipe);
+ struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
r600_blitter_save_states(rctx);
- util_blitter_save_framebuffer(rctx->blitter, &rctx->fb_state);
+ util_blitter_save_framebuffer(rctx->blitter, fb);
util_blitter_clear_render_target(rctx->blitter, dst, rgba,
dstx, dsty, width, height);
@@ -90,9 +97,10 @@ static void r600_clear_depth_stencil(struct pipe_context *pipe,
unsigned width, unsigned height)
{
struct r600_context *rctx = r600_context(pipe);
+ struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
r600_blitter_save_states(rctx);
- util_blitter_save_framebuffer(rctx->blitter, &rctx->fb_state);
+ util_blitter_save_framebuffer(rctx->blitter, fb);
util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil,
dstx, dsty, width, height);
diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c
index bc6e336ba7..7829a479c2 100644
--- a/src/gallium/drivers/r600/r600_buffer.c
+++ b/src/gallium/drivers/r600/r600_buffer.c
@@ -32,10 +32,11 @@
#include "state_tracker/drm_driver.h"
#include "r600_screen.h"
#include "r600_context.h"
+#include "r600_resource.h"
extern struct u_resource_vtbl r600_buffer_vtbl;
-static u32 r600_domain_from_usage(unsigned usage)
+u32 r600_domain_from_usage(unsigned usage)
{
u32 domain = RADEON_GEM_DOMAIN_GTT;
@@ -63,47 +64,47 @@ struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
const struct pipe_resource *templ)
{
struct r600_screen *rscreen = r600_screen(screen);
- struct r600_buffer *rbuffer;
+ struct r600_resource *rbuffer;
struct radeon_bo *bo;
struct pb_desc desc;
/* XXX We probably want a different alignment for buffers and textures. */
unsigned alignment = 4096;
- rbuffer = CALLOC_STRUCT(r600_buffer);
+ rbuffer = CALLOC_STRUCT(r600_resource);
if (rbuffer == NULL)
return NULL;
- rbuffer->b.b = *templ;
- pipe_reference_init(&rbuffer->b.b.reference, 1);
- rbuffer->b.b.screen = screen;
- rbuffer->b.vtbl = &r600_buffer_vtbl;
+ rbuffer->base.b = *templ;
+ pipe_reference_init(&rbuffer->base.b.reference, 1);
+ rbuffer->base.b.screen = screen;
+ rbuffer->base.vtbl = &r600_buffer_vtbl;
- if (rbuffer->b.b.bind & PIPE_BIND_CONSTANT_BUFFER) {
+ if (rbuffer->base.b.bind & PIPE_BIND_CONSTANT_BUFFER) {
desc.alignment = alignment;
- desc.usage = rbuffer->b.b.bind;
- rbuffer->pb = pb_malloc_buffer_create(rbuffer->b.b.width0,
+ desc.usage = rbuffer->base.b.bind;
+ rbuffer->pb = pb_malloc_buffer_create(rbuffer->base.b.width0,
&desc);
if (rbuffer->pb == NULL) {
free(rbuffer);
return NULL;
}
- return &rbuffer->b.b;
+ return &rbuffer->base.b;
}
- rbuffer->domain = r600_domain_from_usage(rbuffer->b.b.bind);
- bo = radeon_bo(rscreen->rw, 0, rbuffer->b.b.width0, alignment, NULL);
+ rbuffer->domain = r600_domain_from_usage(rbuffer->base.b.bind);
+ bo = radeon_bo(rscreen->rw, 0, rbuffer->base.b.width0, alignment, NULL);
if (bo == NULL) {
FREE(rbuffer);
return NULL;
}
rbuffer->bo = bo;
- return &rbuffer->b.b;
+ return &rbuffer->base.b;
}
struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen,
void *ptr, unsigned bytes,
unsigned bind)
{
- struct r600_buffer *rbuffer;
+ struct r600_resource *rbuffer;
struct r600_screen *rscreen = r600_screen(screen);
struct pipe_resource templ;
@@ -116,20 +117,20 @@ struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen,
templ.height0 = 1;
templ.depth0 = 1;
- rbuffer = (struct r600_buffer*)r600_buffer_create(screen, &templ);
+ rbuffer = (struct r600_resource*)r600_buffer_create(screen, &templ);
if (rbuffer == NULL) {
return NULL;
}
radeon_bo_map(rscreen->rw, rbuffer->bo);
memcpy(rbuffer->bo->data, ptr, bytes);
radeon_bo_unmap(rscreen->rw, rbuffer->bo);
- return &rbuffer->b.b;
+ return &rbuffer->base.b;
}
static void r600_buffer_destroy(struct pipe_screen *screen,
struct pipe_resource *buf)
{
- struct r600_buffer *rbuffer = (struct r600_buffer*)buf;
+ struct r600_resource *rbuffer = (struct r600_resource*)buf;
struct r600_screen *rscreen = r600_screen(screen);
if (rbuffer->pb) {
@@ -140,13 +141,14 @@ static void r600_buffer_destroy(struct pipe_screen *screen,
if (rbuffer->bo) {
radeon_bo_decref(rscreen->rw, rbuffer->bo);
}
+ memset(rbuffer, 0, sizeof(struct r600_resource));
FREE(rbuffer);
}
static void *r600_buffer_transfer_map(struct pipe_context *pipe,
struct pipe_transfer *transfer)
{
- struct r600_buffer *rbuffer = (struct r600_buffer*)transfer->resource;
+ struct r600_resource *rbuffer = (struct r600_resource*)transfer->resource;
struct r600_screen *rscreen = r600_screen(pipe->screen);
int write = 0;
@@ -166,9 +168,9 @@ static void *r600_buffer_transfer_map(struct pipe_context *pipe,
}
static void r600_buffer_transfer_unmap(struct pipe_context *pipe,
- struct pipe_transfer *transfer)
+ struct pipe_transfer *transfer)
{
- struct r600_buffer *rbuffer = (struct r600_buffer*)transfer->resource;
+ struct r600_resource *rbuffer = (struct r600_resource*)transfer->resource;
struct r600_screen *rscreen = r600_screen(pipe->screen);
if (rbuffer->pb) {
@@ -188,7 +190,7 @@ unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context,
struct pipe_resource *buf,
unsigned face, unsigned level)
{
- /* XXX */
+ /* FIXME */
return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
}
@@ -196,7 +198,7 @@ struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen,
struct winsys_handle *whandle)
{
struct radeon *rw = (struct radeon*)screen->winsys;
- struct r600_buffer *rbuffer;
+ struct r600_resource *rbuffer;
struct radeon_bo *bo = NULL;
bo = radeon_bo(rw, whandle->handle, 0, 0, NULL);
@@ -204,18 +206,18 @@ struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen,
return NULL;
}
- rbuffer = CALLOC_STRUCT(r600_buffer);
+ rbuffer = CALLOC_STRUCT(r600_resource);
if (rbuffer == NULL) {
radeon_bo_decref(rw, bo);
return NULL;
}
- pipe_reference_init(&rbuffer->b.b.reference, 1);
- rbuffer->b.b.target = PIPE_BUFFER;
- rbuffer->b.b.screen = screen;
- rbuffer->b.vtbl = &r600_buffer_vtbl;
+ pipe_reference_init(&rbuffer->base.b.reference, 1);
+ rbuffer->base.b.target = PIPE_BUFFER;
+ rbuffer->base.b.screen = screen;
+ rbuffer->base.vtbl = &r600_buffer_vtbl;
rbuffer->bo = bo;
- return &rbuffer->b.b;
+ return &rbuffer->base.b;
}
struct u_resource_vtbl r600_buffer_vtbl =
diff --git a/src/gallium/drivers/r600/r600_compiler.c b/src/gallium/drivers/r600/r600_compiler.c
deleted file mode 100644
index 1804b86d24..0000000000
--- a/src/gallium/drivers/r600/r600_compiler.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * Copyright 2010 Jerome Glisse <glisse@freedesktop.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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <errno.h>
-#include "r600_compiler.h"
-
-struct c_vector *c_vector_new(void)
-{
- struct c_vector *v = calloc(1, sizeof(struct c_vector));
-
- if (v == NULL) {
- return NULL;
- }
- LIST_INITHEAD(&v->head);
- return v;
-}
-
-static unsigned c_opcode_is_alu(unsigned opcode)
-{
- switch (opcode) {
- case C_OPCODE_MOV:
- case C_OPCODE_MUL:
- case C_OPCODE_MAD:
- case C_OPCODE_ARL:
- case C_OPCODE_LIT:
- case C_OPCODE_RCP:
- case C_OPCODE_RSQ:
- case C_OPCODE_EXP:
- case C_OPCODE_LOG:
- case C_OPCODE_ADD:
- case C_OPCODE_DP3:
- case C_OPCODE_DP4:
- case C_OPCODE_DST:
- case C_OPCODE_MIN:
- case C_OPCODE_MAX:
- case C_OPCODE_SLT:
- case C_OPCODE_SGE:
- case C_OPCODE_SUB:
- case C_OPCODE_LRP:
- case C_OPCODE_CND:
- case C_OPCODE_DP2A:
- case C_OPCODE_FRC:
- case C_OPCODE_CLAMP:
- case C_OPCODE_FLR:
- case C_OPCODE_ROUND:
- case C_OPCODE_EX2:
- case C_OPCODE_LG2:
- case C_OPCODE_POW:
- case C_OPCODE_XPD:
- case C_OPCODE_ABS:
- case C_OPCODE_RCC:
- case C_OPCODE_DPH:
- case C_OPCODE_COS:
- case C_OPCODE_DDX:
- case C_OPCODE_DDY:
- case C_OPCODE_PK2H:
- case C_OPCODE_PK2US:
- case C_OPCODE_PK4B:
- case C_OPCODE_PK4UB:
- case C_OPCODE_RFL:
- case C_OPCODE_SEQ:
- case C_OPCODE_SFL:
- case C_OPCODE_SGT:
- case C_OPCODE_SIN:
- case C_OPCODE_SLE:
- case C_OPCODE_SNE:
- case C_OPCODE_STR:
- case C_OPCODE_UP2H:
- case C_OPCODE_UP2US:
- case C_OPCODE_UP4B:
- case C_OPCODE_UP4UB:
- case C_OPCODE_X2D:
- case C_OPCODE_ARA:
- case C_OPCODE_ARR:
- case C_OPCODE_BRA:
- case C_OPCODE_SSG:
- case C_OPCODE_CMP:
- case C_OPCODE_SCS:
- case C_OPCODE_NRM:
- case C_OPCODE_DIV:
- case C_OPCODE_DP2:
- case C_OPCODE_CEIL:
- case C_OPCODE_I2F:
- case C_OPCODE_NOT:
- case C_OPCODE_TRUNC:
- case C_OPCODE_SHL:
- case C_OPCODE_AND:
- case C_OPCODE_OR:
- case C_OPCODE_MOD:
- case C_OPCODE_XOR:
- case C_OPCODE_SAD:
- case C_OPCODE_NRM4:
- case C_OPCODE_F2I:
- case C_OPCODE_IDIV:
- case C_OPCODE_IMAX:
- case C_OPCODE_IMIN:
- case C_OPCODE_INEG:
- case C_OPCODE_ISGE:
- case C_OPCODE_ISHR:
- case C_OPCODE_ISLT:
- case C_OPCODE_F2U:
- case C_OPCODE_U2F:
- case C_OPCODE_UADD:
- case C_OPCODE_UDIV:
- case C_OPCODE_UMAD:
- case C_OPCODE_UMAX:
- case C_OPCODE_UMIN:
- case C_OPCODE_UMOD:
- case C_OPCODE_UMUL:
- case C_OPCODE_USEQ:
- case C_OPCODE_USGE:
- case C_OPCODE_USHR:
- case C_OPCODE_USLT:
- case C_OPCODE_USNE:
- return 1;
- case C_OPCODE_END:
- case C_OPCODE_VFETCH:
- case C_OPCODE_KILP:
- case C_OPCODE_CAL:
- case C_OPCODE_RET:
- case C_OPCODE_TXB:
- case C_OPCODE_TXL:
- case C_OPCODE_BRK:
- case C_OPCODE_IF:
- case C_OPCODE_BGNFOR:
- case C_OPCODE_REP:
- case C_OPCODE_ELSE:
- case C_OPCODE_ENDIF:
- case C_OPCODE_ENDFOR:
- case C_OPCODE_ENDREP:
- case C_OPCODE_PUSHA:
- case C_OPCODE_POPA:
- case C_OPCODE_TXF:
- case C_OPCODE_TXQ:
- case C_OPCODE_CONT:
- case C_OPCODE_EMIT:
- case C_OPCODE_ENDPRIM:
- case C_OPCODE_BGNLOOP:
- case C_OPCODE_BGNSUB:
- case C_OPCODE_ENDLOOP:
- case C_OPCODE_ENDSUB:
- case C_OPCODE_NOP:
- case C_OPCODE_CALLNZ:
- case C_OPCODE_IFC:
- case C_OPCODE_BREAKC:
- case C_OPCODE_KIL:
- case C_OPCODE_TEX:
- case C_OPCODE_TXD:
- case C_OPCODE_TXP:
- case C_OPCODE_SWITCH:
- case C_OPCODE_CASE:
- case C_OPCODE_DEFAULT:
- case C_OPCODE_ENDSWITCH:
- default:
- return 0;
- }
-}
-
-
-/* NEW */
-void c_node_init(struct c_node *node)
-{
- memset(node, 0, sizeof(struct c_node));
- LIST_INITHEAD(&node->predecessors);
- LIST_INITHEAD(&node->successors);
- LIST_INITHEAD(&node->childs);
- LIST_INITHEAD(&node->insts);
- node->parent = NULL;
-}
-
-static struct c_node_link *c_node_link_new(struct c_node *node)
-{
- struct c_node_link *link;
-
- link = calloc(1, sizeof(struct c_node_link));
- if (link == NULL)
- return NULL;
- LIST_INITHEAD(&link->head);
- link->node = node;
- return link;
-}
-
-int c_node_cfg_link(struct c_node *predecessor, struct c_node *successor)
-{
- struct c_node_link *pedge, *sedge;
-
- pedge = c_node_link_new(successor);
- sedge = c_node_link_new(predecessor);
- if (sedge == NULL || pedge == NULL) {
- free(sedge);
- free(pedge);
- return -ENOMEM;
- }
- LIST_ADDTAIL(&pedge->head, &predecessor->successors);
- LIST_ADDTAIL(&sedge->head, &successor->predecessors);
-
- return 0;
-}
-
-int c_node_add_new_instruction_head(struct c_node *node, struct c_instruction *instruction)
-{
- struct c_instruction *inst = malloc(sizeof(struct c_instruction));
-
- if (inst == NULL)
- return -ENOMEM;
- memcpy(inst, instruction, sizeof(struct c_instruction));
- LIST_ADD(&inst->head, &node->insts);
- return 0;
-}
-
-int c_node_add_new_instruction(struct c_node *node, struct c_instruction *instruction)
-{
- struct c_instruction *inst = malloc(sizeof(struct c_instruction));
-
- if (inst == NULL)
- return -ENOMEM;
- memcpy(inst, instruction, sizeof(struct c_instruction));
- LIST_ADDTAIL(&inst->head, &node->insts);
- return 0;
-}
-
-struct c_node *c_shader_cfg_new_node_after(struct c_shader *shader, struct c_node *predecessor)
-{
- struct c_node *node = calloc(1, sizeof(struct c_node));
-
- if (node == NULL)
- return NULL;
- c_node_init(node);
- if (c_node_cfg_link(predecessor, node)) {
- free(node);
- return NULL;
- }
- LIST_ADDTAIL(&node->head, &shader->nodes);
- return node;
-}
-
-int c_shader_init(struct c_shader *shader, unsigned type)
-{
- unsigned i;
- int r;
-
- shader->type = type;
- for (i = 0; i < C_FILE_COUNT; i++) {
- shader->files[i].nvectors = 0;
- LIST_INITHEAD(&shader->files[i].vectors);
- }
- LIST_INITHEAD(&shader->nodes);
- c_node_init(&shader->entry);
- c_node_init(&shader->end);
- shader->entry.opcode = C_OPCODE_ENTRY;
- shader->end.opcode = C_OPCODE_END;
- r = c_node_cfg_link(&shader->entry, &shader->end);
- if (r)
- return r;
- return 0;
-}
-
-struct c_vector *c_shader_vector_new(struct c_shader *shader, unsigned file, unsigned name, int sid)
-{
- struct c_vector *v = calloc(1, sizeof(struct c_vector));
- int i;
-
- if (v == NULL) {
- return NULL;
- }
- for (i = 0; i < 4; i++) {
- v->channel[i] = calloc(1, sizeof(struct c_channel));
- if (v->channel[i] == NULL)
- goto out_err;
- v->channel[i]->vindex = i;
- v->channel[i]->vector = v;
- }
- v->file = file;
- v->name = name;
- v->sid = sid;
- shader->files[v->file].nvectors++;
- v->id = shader->nvectors++;
- LIST_ADDTAIL(&v->head, &shader->files[v->file].vectors);
- return v;
-out_err:
- for (i = 0; i < 4; i++) {
- free(v->channel[i]);
- }
- free(v);
- return NULL;
-}
-
-static void c_node_remove_link(struct list_head *head, struct c_node *node)
-{
- struct c_node_link *link, *tmp;
-
- LIST_FOR_EACH_ENTRY_SAFE(link, tmp, head, head) {
- if (link->node == node) {
- LIST_DEL(&link->head);
- free(link);
- }
- }
-}
-
-static void c_node_destroy(struct c_node *node)
-{
- struct c_instruction *i, *ni;
- struct c_node_link *link, *tmp;
-
- LIST_FOR_EACH_ENTRY_SAFE(i, ni, &node->insts, head) {
- LIST_DEL(&i->head);
- free(i);
- }
- if (node->parent)
- c_node_remove_link(&node->parent->childs, node);
- node->parent = NULL;
- LIST_FOR_EACH_ENTRY_SAFE(link, tmp, &node->predecessors, head) {
- c_node_remove_link(&link->node->successors, node);
- LIST_DEL(&link->head);
- free(link);
- }
- LIST_FOR_EACH_ENTRY_SAFE(link, tmp, &node->successors, head) {
- c_node_remove_link(&link->node->predecessors, node);
- LIST_DEL(&link->head);
- free(link);
- }
- LIST_FOR_EACH_ENTRY_SAFE(link, tmp, &node->childs, head) {
- link->node->parent = NULL;
- LIST_DEL(&link->head);
- free(link);
- }
-}
-
-void c_shader_destroy(struct c_shader *shader)
-{
- struct c_node *n, *nn;
- struct c_vector *v, *nv;
- unsigned i;
-
- for (i = 0; i < C_FILE_COUNT; i++) {
- shader->files[i].nvectors = 0;
- LIST_FOR_EACH_ENTRY_SAFE(v, nv, &shader->files[i].vectors, head) {
- LIST_DEL(&v->head);
- free(v->channel[0]);
- free(v->channel[1]);
- free(v->channel[2]);
- free(v->channel[3]);
- free(v);
- }
- }
- LIST_FOR_EACH_ENTRY_SAFE(n, nn, &shader->nodes, head) {
- LIST_DEL(&n->head);
- c_node_destroy(n);
- }
- memset(shader, 0, sizeof(struct c_shader));
-}
-
-static void c_shader_dfs_without_rec(struct c_node *entry, struct c_node *node)
-{
- struct c_node_link *link;
-
- if (entry == node || entry->visited)
- return;
- entry->visited = 1;
- LIST_FOR_EACH_ENTRY(link, &entry->successors, head) {
- c_shader_dfs_without_rec(link->node, node);
- }
-}
-
-static void c_shader_dfs_without(struct c_shader *shader, struct c_node *node)
-{
- struct c_node *n;
-
- shader->entry.visited = 0;
- shader->end.visited = 0;
- LIST_FOR_EACH_ENTRY(n, &shader->nodes, head) {
- n->visited = 0;
- }
- c_shader_dfs_without_rec(&shader->entry, node);
-}
-
-static int c_shader_build_dominator_tree_rec(struct c_shader *shader, struct c_node *node)
-{
- struct c_node_link *link, *nlink;
- unsigned found = 0;
- int r;
-
- if (node->done)
- return 0;
- node->done = 1;
- LIST_FOR_EACH_ENTRY(link, &node->predecessors, head) {
- /* if we remove this predecessor can we reach the current node ? */
- c_shader_dfs_without(shader, link->node);
- if (node->visited == 0) {
- /* we were unable to visit current node thus current
- * predecessor is the immediate dominator of node, as
- * their can be only one immediate dominator we break
- */
- node->parent = link->node;
- nlink = c_node_link_new(node);
- if (nlink == NULL)
- return -ENOMEM;
- LIST_ADDTAIL(&nlink->head, &link->node->childs);
- found = 1;
- break;
- }
- }
- /* this shouldn't happen there should at least be 1 denominator for each node */
- if (!found && node->opcode != C_OPCODE_ENTRY) {
- fprintf(stderr, "invalid flow control graph node %p (%d) has no immediate dominator\n",
- node, node->opcode);
- return -EINVAL;
- }
- LIST_FOR_EACH_ENTRY(link, &node->predecessors, head) {
- r = c_shader_build_dominator_tree_rec(shader, link->node);
- if (r)
- return r;
- }
- return 0;
-}
-
-int c_shader_build_dominator_tree(struct c_shader *shader)
-{
- struct c_node *node;
- LIST_FOR_EACH_ENTRY(node, &shader->nodes, head) {
- node->done = 0;
- }
- return c_shader_build_dominator_tree_rec(shader, &shader->end);
-}
diff --git a/src/gallium/drivers/r600/r600_compiler.h b/src/gallium/drivers/r600/r600_compiler.h
deleted file mode 100644
index 77230aed73..0000000000
--- a/src/gallium/drivers/r600/r600_compiler.h
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright 2010 Jerome Glisse <glisse@freedesktop.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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef R600_COMPILER_H
-#define R600_COMPILER_H
-
-#include "util/u_double_list.h"
-
-struct c_vector;
-
-/* operand are the basic source/destination of each operation */
-struct c_channel {
- struct list_head head;
- unsigned vindex; /**< index in vector X,Y,Z,W (0,1,2,3) */
- unsigned value; /**< immediate value 32bits */
- struct c_vector *vector; /**< vector to which it belongs */
-};
-
-/* in GPU world most of the time operand are grouped into vector
- * of 4 component this structure is mostly and handler to group
- * operand into a same vector
- */
-struct c_vector {
- struct list_head head;
- unsigned id; /**< vector uniq id */
- unsigned name; /**< semantic name */
- unsigned file; /**< operand file C_FILE_* */
- int sid; /**< semantic id */
- struct c_channel *channel[4]; /**< operands */
-};
-
-#define C_PROGRAM_TYPE_VS 0
-#define C_PROGRAM_TYPE_FS 1
-#define C_PROGRAM_TYPE_COUNT 2
-
-#define C_NODE_FLAG_ALU 1
-#define C_NODE_FLAG_FETCH 2
-
-#define C_SWIZZLE_X 0
-#define C_SWIZZLE_Y 1
-#define C_SWIZZLE_Z 2
-#define C_SWIZZLE_W 3
-#define C_SWIZZLE_0 4
-#define C_SWIZZLE_1 5
-#define C_SWIZZLE_D 6
-
-#define C_FILE_NULL 0
-#define C_FILE_CONSTANT 1
-#define C_FILE_INPUT 2
-#define C_FILE_OUTPUT 3
-#define C_FILE_TEMPORARY 4
-#define C_FILE_SAMPLER 5
-#define C_FILE_ADDRESS 6
-#define C_FILE_IMMEDIATE 7
-#define C_FILE_LOOP 8
-#define C_FILE_PREDICATE 9
-#define C_FILE_SYSTEM_VALUE 10
-#define C_FILE_RESOURCE 11
-#define C_FILE_COUNT 12
-
-#define C_SEMANTIC_POSITION 0
-#define C_SEMANTIC_COLOR 1
-#define C_SEMANTIC_BCOLOR 2 /**< back-face color */
-#define C_SEMANTIC_FOG 3
-#define C_SEMANTIC_PSIZE 4
-#define C_SEMANTIC_GENERIC 5
-#define C_SEMANTIC_NORMAL 6
-#define C_SEMANTIC_FACE 7
-#define C_SEMANTIC_EDGEFLAG 8
-#define C_SEMANTIC_PRIMID 9
-#define C_SEMANTIC_INSTANCEID 10
-#define C_SEMANTIC_VERTEXID 11
-#define C_SEMANTIC_COUNT 12 /**< number of semantic values */
-
-#define C_OPCODE_NOP 0
-#define C_OPCODE_MOV 1
-#define C_OPCODE_LIT 2
-#define C_OPCODE_RCP 3
-#define C_OPCODE_RSQ 4
-#define C_OPCODE_EXP 5
-#define C_OPCODE_LOG 6
-#define C_OPCODE_MUL 7
-#define C_OPCODE_ADD 8
-#define C_OPCODE_DP3 9
-#define C_OPCODE_DP4 10
-#define C_OPCODE_DST 11
-#define C_OPCODE_MIN 12
-#define C_OPCODE_MAX 13
-#define C_OPCODE_SLT 14
-#define C_OPCODE_SGE 15
-#define C_OPCODE_MAD 16
-#define C_OPCODE_SUB 17
-#define C_OPCODE_LRP 18
-#define C_OPCODE_CND 19
-/* gap */
-#define C_OPCODE_DP2A 21
-/* gap */
-#define C_OPCODE_FRC 24
-#define C_OPCODE_CLAMP 25
-#define C_OPCODE_FLR 26
-#define C_OPCODE_ROUND 27
-#define C_OPCODE_EX2 28
-#define C_OPCODE_LG2 29
-#define C_OPCODE_POW 30
-#define C_OPCODE_XPD 31
-/* gap */
-#define C_OPCODE_ABS 33
-#define C_OPCODE_RCC 34
-#define C_OPCODE_DPH 35
-#define C_OPCODE_COS 36
-#define C_OPCODE_DDX 37
-#define C_OPCODE_DDY 38
-#define C_OPCODE_KILP 39 /* predicated kill */
-#define C_OPCODE_PK2H 40
-#define C_OPCODE_PK2US 41
-#define C_OPCODE_PK4B 42
-#define C_OPCODE_PK4UB 43
-#define C_OPCODE_RFL 44
-#define C_OPCODE_SEQ 45
-#define C_OPCODE_SFL 46
-#define C_OPCODE_SGT 47
-#define C_OPCODE_SIN 48
-#define C_OPCODE_SLE 49
-#define C_OPCODE_SNE 50
-#define C_OPCODE_STR 51
-#define C_OPCODE_TEX 52
-#define C_OPCODE_TXD 53
-#define C_OPCODE_TXP 54
-#define C_OPCODE_UP2H 55
-#define C_OPCODE_UP2US 56
-#define C_OPCODE_UP4B 57
-#define C_OPCODE_UP4UB 58
-#define C_OPCODE_X2D 59
-#define C_OPCODE_ARA 60
-#define C_OPCODE_ARR 61
-#define C_OPCODE_BRA 62
-#define C_OPCODE_CAL 63
-#define C_OPCODE_RET 64
-#define C_OPCODE_SSG 65 /* SGN */
-#define C_OPCODE_CMP 66
-#define C_OPCODE_SCS 67
-#define C_OPCODE_TXB 68
-#define C_OPCODE_NRM 69
-#define C_OPCODE_DIV 70
-#define C_OPCODE_DP2 71
-#define C_OPCODE_TXL 72
-#define C_OPCODE_BRK 73
-#define C_OPCODE_IF 74
-#define C_OPCODE_BGNFOR 75
-#define C_OPCODE_REP 76
-#define C_OPCODE_ELSE 77
-#define C_OPCODE_ENDIF 78
-#define C_OPCODE_ENDFOR 79
-#define C_OPCODE_ENDREP 80
-#define C_OPCODE_PUSHA 81
-#define C_OPCODE_POPA 82
-#define C_OPCODE_CEIL 83
-#define C_OPCODE_I2F 84
-#define C_OPCODE_NOT 85
-#define C_OPCODE_TRUNC 86
-#define C_OPCODE_SHL 87
-/* gap */
-#define C_OPCODE_AND 89
-#define C_OPCODE_OR 90
-#define C_OPCODE_MOD 91
-#define C_OPCODE_XOR 92
-#define C_OPCODE_SAD 93
-#define C_OPCODE_TXF 94
-#define C_OPCODE_TXQ 95
-#define C_OPCODE_CONT 96
-#define C_OPCODE_EMIT 97
-#define C_OPCODE_ENDPRIM 98
-#define C_OPCODE_BGNLOOP 99
-#define C_OPCODE_BGNSUB 100
-#define C_OPCODE_ENDLOOP 101
-#define C_OPCODE_ENDSUB 102
-/* gap */
-#define C_OPCODE_NRM4 112
-#define C_OPCODE_CALLNZ 113
-#define C_OPCODE_IFC 114
-#define C_OPCODE_BREAKC 115
-#define C_OPCODE_KIL 116 /* conditional kill */
-#define C_OPCODE_END 117 /* aka HALT */
-/* gap */
-#define C_OPCODE_F2I 119
-#define C_OPCODE_IDIV 120
-#define C_OPCODE_IMAX 121
-#define C_OPCODE_IMIN 122
-#define C_OPCODE_INEG 123
-#define C_OPCODE_ISGE 124
-#define C_OPCODE_ISHR 125
-#define C_OPCODE_ISLT 126
-#define C_OPCODE_F2U 127
-#define C_OPCODE_U2F 128
-#define C_OPCODE_UADD 129
-#define C_OPCODE_UDIV 130
-#define C_OPCODE_UMAD 131
-#define C_OPCODE_UMAX 132
-#define C_OPCODE_UMIN 133
-#define C_OPCODE_UMOD 134
-#define C_OPCODE_UMUL 135
-#define C_OPCODE_USEQ 136
-#define C_OPCODE_USGE 137
-#define C_OPCODE_USHR 138
-#define C_OPCODE_USLT 139
-#define C_OPCODE_USNE 140
-#define C_OPCODE_SWITCH 141
-#define C_OPCODE_CASE 142
-#define C_OPCODE_DEFAULT 143
-#define C_OPCODE_ENDSWITCH 144
-#define C_OPCODE_VFETCH 145
-#define C_OPCODE_ENTRY 146
-#define C_OPCODE_ARL 147
-#define C_OPCODE_LAST 148
-
-#define C_OPERAND_FLAG_ABS (1 << 0)
-#define C_OPERAND_FLAG_NEG (1 << 1)
-
-struct c_operand {
- struct c_vector *vector;
- unsigned swizzle;
- unsigned flag;
-};
-
-struct c_op {
- unsigned ninput;
- struct c_operand input[3];
- struct c_operand output;
- unsigned opcode;
-};
-
-struct c_instruction {
- struct list_head head;
- unsigned nop;
- struct c_op op[5];
-};
-
-struct c_node;
-
-struct c_node_link {
- struct list_head head;
- struct c_node *node;
-};
-
-/**
- * struct c_node
- *
- * @next: all node are in a double linked list, this point to
- * next node
- * @next: all node are in a double linked list, this point to
- * previous node
- * @predecessors: list of all predecessor nodes in the flow graph
- * @successors: list of all sucessor nodes in the flow graph
- * @parent: parent node in the depth first walk tree
- * @childs: child nodes in the depth first walk tree
- */
-struct c_node {
- struct list_head head;
- struct list_head predecessors;
- struct list_head successors;
- struct list_head childs;
- struct c_node *parent;
- struct list_head insts;
- unsigned opcode;
- unsigned visited;
- unsigned done;
- void *backend;
-};
-
-struct c_file {
- unsigned nvectors;
- struct list_head vectors;
-};
-
-struct c_shader {
- unsigned nvectors;
- struct c_file files[C_FILE_COUNT];
- struct list_head nodes;
- struct c_node entry;
- struct c_node end;
- unsigned type;
-};
-
-int c_shader_init(struct c_shader *shader, unsigned type);
-void c_shader_destroy(struct c_shader *shader);
-struct c_vector *c_shader_vector_new(struct c_shader *shader, unsigned file, unsigned name, int sid);
-int c_shader_build_dominator_tree(struct c_shader *shader);
-void c_shader_dump(struct c_shader *shader);
-
-void c_node_init(struct c_node *node);
-int c_node_add_new_instruction(struct c_node *node, struct c_instruction *instruction);
-int c_node_add_new_instruction_head(struct c_node *node, struct c_instruction *instruction);
-
-/* control flow graph functions */
-int c_node_cfg_link(struct c_node *predecessor, struct c_node *successor);
-struct c_node *c_node_cfg_new_after(struct c_node *predecessor);
-struct c_node *c_shader_cfg_new_node_after(struct c_shader *shader, struct c_node *predecessor);
-
-struct c_vector *c_vector_new(void);
-
-#endif
diff --git a/src/gallium/drivers/r600/r600_compiler_dump.c b/src/gallium/drivers/r600/r600_compiler_dump.c
deleted file mode 100644
index bb022b7c29..0000000000
--- a/src/gallium/drivers/r600/r600_compiler_dump.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright 2010 Jerome Glisse <glisse@freedesktop.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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdio.h>
-#include "r600_compiler.h"
-
-static const char *c_file_swz[] = {
- "x",
- "y",
- "z",
- "w",
- "0",
- "1",
- ".",
-};
-
-static const char *c_file_str[] = {
- "NULL",
- "CONSTANT",
- "INPUT",
- "OUTPUT",
- "TEMPORARY",
- "SAMPLER",
- "ADDRESS",
- "IMMEDIATE",
- "LOOP",
- "PREDICATE",
- "SYSTEM_VALUE",
-};
-
-static const char *c_semantic_str[] = {
- "POSITION",
- "COLOR",
- "BCOLOR",
- "FOG",
- "PSIZE",
- "GENERIC",
- "NORMAL",
- "FACE",
- "EDGEFLAG",
- "PRIMID",
- "INSTANCEID",
-};
-
-static const char *c_opcode_str[] = {
- "ARL",
- "MOV",
- "LIT",
- "RCP",
- "RSQ",
- "EXP",
- "LOG",
- "MUL",
- "ADD",
- "DP3",
- "DP4",
- "DST",
- "MIN",
- "MAX",
- "SLT",
- "SGE",
- "MAD",
- "SUB",
- "LRP",
- "CND",
- "(INVALID)",
- "DP2A",
- "(INVALID)",
- "(INVALID)",
- "FRC",
- "CLAMP",
- "FLR",
- "ROUND",
- "EX2",
- "LG2",
- "POW",
- "XPD",
- "(INVALID)",
- "ABS",
- "RCC",
- "DPH",
- "COS",
- "DDX",
- "DDY",
- "KILP",
- "PK2H",
- "PK2US",
- "PK4B",
- "PK4UB",
- "RFL",
- "SEQ",
- "SFL",
- "SGT",
- "SIN",
- "SLE",
- "SNE",
- "STR",
- "TEX",
- "TXD",
- "TXP",
- "UP2H",
- "UP2US",
- "UP4B",
- "UP4UB",
- "X2D",
- "ARA",
- "ARR",
- "BRA",
- "CAL",
- "RET",
- "SSG",
- "CMP",
- "SCS",
- "TXB",
- "NRM",
- "DIV",
- "DP2",
- "TXL",
- "BRK",
- "IF",
- "BGNFOR",
- "REP",
- "ELSE",
- "ENDIF",
- "ENDFOR",
- "ENDREP",
- "PUSHA",
- "POPA",
- "CEIL",
- "I2F",
- "NOT",
- "TRUNC",
- "SHL",
- "(INVALID)",
- "AND",
- "OR",
- "MOD",
- "XOR",
- "SAD",
- "TXF",
- "TXQ",
- "CONT",
- "EMIT",
- "ENDPRIM",
- "BGNLOOP",
- "BGNSUB",
- "ENDLOOP",
- "ENDSUB",
- "(INVALID)",
- "(INVALID)",
- "(INVALID)",
- "(INVALID)",
- "NOP",
- "(INVALID)",
- "(INVALID)",
- "(INVALID)",
- "(INVALID)",
- "NRM4",
- "CALLNZ",
- "IFC",
- "BREAKC",
- "KIL",
- "END",
- "(INVALID)",
- "F2I",
- "IDIV",
- "IMAX",
- "IMIN",
- "INEG",
- "ISGE",
- "ISHR",
- "ISLT",
- "F2U",
- "U2F",
- "UADD",
- "UDIV",
- "UMAD",
- "UMAX",
- "UMIN",
- "UMOD",
- "UMUL",
- "USEQ",
- "USGE",
- "USHR",
- "USLT",
- "USNE",
- "SWITCH",
- "CASE",
- "DEFAULT",
- "ENDSWITCH",
- "VFETCH",
- "ENTRY",
-};
-
-static inline const char *c_get_name(const char *name[], unsigned i)
-{
- return name[i];
-}
-
-static void pindent(unsigned indent)
-{
- unsigned i;
- for (i = 0; i < indent; i++)
- fprintf(stderr, " ");
-}
-
-static void c_node_dump(struct c_node *node, unsigned indent)
-{
- struct c_instruction *i;
- unsigned j, k;
-
- pindent(indent); fprintf(stderr, "# node %s\n", c_get_name(c_opcode_str, node->opcode));
- LIST_FOR_EACH_ENTRY(i, &node->insts, head) {
- for (k = 0; k < i->nop; k++) {
- pindent(indent);
- fprintf(stderr, "%s", c_get_name(c_opcode_str, i->op[k].opcode));
- fprintf(stderr, " %s[%d][%s]",
- c_get_name(c_file_str, i->op[k].output.vector->file),
- i->op[k].output.vector->id,
- c_get_name(c_file_swz, i->op[k].output.swizzle));
- for (j = 0; j < i->op[k].ninput; j++) {
- fprintf(stderr, " %s[%d][%s]",
- c_get_name(c_file_str, i->op[k].input[j].vector->file),
- i->op[k].input[j].vector->id,
- c_get_name(c_file_swz, i->op[k].input[j].swizzle));
- }
- fprintf(stderr, ";\n");
- }
- }
-}
-
-static void c_shader_dump_rec(struct c_shader *shader, struct c_node *node, unsigned indent)
-{
- struct c_node_link *link;
-
- c_node_dump(node, indent);
- LIST_FOR_EACH_ENTRY(link, &node->childs, head) {
- c_shader_dump_rec(shader, link->node, indent + 1);
- }
-}
-
-void c_shader_dump(struct c_shader *shader)
-{
- c_shader_dump_rec(shader, &shader->entry, 0);
-}
diff --git a/src/gallium/drivers/r600/r600_compiler_r600.c b/src/gallium/drivers/r600/r600_compiler_r600.c
deleted file mode 100644
index 27ad8f1a18..0000000000
--- a/src/gallium/drivers/r600/r600_compiler_r600.c
+++ /dev/null
@@ -1,972 +0,0 @@
-/*
- * Copyright 2010 Jerome Glisse <glisse@freedesktop.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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <errno.h>
-#include <util/u_format.h>
-#include "r600_screen.h"
-#include "r600_context.h"
-#include "r600_sq.h"
-
-
-struct r600_alu_instruction {
- unsigned copcode;
- enum r600_instruction instruction;
-};
-
-static int r600_shader_alu_translate(struct r600_shader *rshader,
- struct r600_shader_node *node,
- struct c_instruction *instruction);
-struct r600_alu_instruction r600_alu_instruction[C_OPCODE_LAST];
-struct r600_instruction_info r600_instruction_info[];
-
-int r600_shader_insert_fetch(struct c_shader *shader)
-{
- struct c_vector *vi, *vr, *v, *nv;
- struct c_instruction instruction;
- int r;
-
- if (shader->type != C_PROGRAM_TYPE_VS)
- return 0;
- vi = c_shader_vector_new(shader, C_FILE_INPUT, C_SEMANTIC_VERTEXID, -1);
- if (vi == NULL)
- return -ENOMEM;
- LIST_FOR_EACH_ENTRY_SAFE(v, nv, &shader->files[C_FILE_INPUT].vectors, head) {
- if (v == vi)
- continue;
- vr = c_shader_vector_new(shader, C_FILE_RESOURCE, C_SEMANTIC_GENERIC, -1);
- if (vr == NULL)
- return -ENOMEM;
- memset(&instruction, 0, sizeof(struct c_instruction));
- instruction.nop = 4;
- instruction.op[0].opcode = C_OPCODE_VFETCH;
- instruction.op[1].opcode = C_OPCODE_VFETCH;
- instruction.op[2].opcode = C_OPCODE_VFETCH;
- instruction.op[3].opcode = C_OPCODE_VFETCH;
- instruction.op[0].ninput = 2;
- instruction.op[1].ninput = 2;
- instruction.op[2].ninput = 2;
- instruction.op[3].ninput = 2;
- instruction.op[0].output.vector = v;
- instruction.op[1].output.vector = v;
- instruction.op[2].output.vector = v;
- instruction.op[3].output.vector = v;
- instruction.op[0].input[0].vector = vi;
- instruction.op[0].input[1].vector = vr;
- instruction.op[1].input[0].vector = vi;
- instruction.op[1].input[1].vector = vr;
- instruction.op[2].input[0].vector = vi;
- instruction.op[2].input[1].vector = vr;
- instruction.op[3].input[0].vector = vi;
- instruction.op[3].input[1].vector = vr;
- instruction.op[0].output.swizzle = C_SWIZZLE_X;
- instruction.op[1].output.swizzle = C_SWIZZLE_Y;
- instruction.op[2].output.swizzle = C_SWIZZLE_Z;
- instruction.op[3].output.swizzle = C_SWIZZLE_W;
- r = c_node_add_new_instruction_head(&shader->entry, &instruction);
- if (r)
- return r;
- LIST_DEL(&v->head);
- shader->files[C_FILE_INPUT].nvectors--;
- LIST_ADDTAIL(&v->head, &shader->files[C_FILE_TEMPORARY].vectors);
- shader->files[C_FILE_TEMPORARY].nvectors++;
- v->file = C_FILE_TEMPORARY;
- }
- return 0;
-}
-
-void r600_shader_cleanup(struct r600_shader *rshader)
-{
- struct r600_shader_node *n, *nn;
- struct r600_shader_vfetch *vf, *nvf;
- struct r600_shader_alu *alu, *nalu;
- int i;
-
- if (rshader == NULL)
- return;
- if (rshader->gpr) {
- for (i = 0; i < rshader->nvector; i++) {
- free(rshader->gpr[i]);
- }
- free(rshader->gpr);
- rshader->gpr = NULL;
- }
- LIST_FOR_EACH_ENTRY_SAFE(n, nn, &rshader->nodes, head) {
- LIST_DEL(&n->head);
- LIST_FOR_EACH_ENTRY_SAFE(vf, nvf, &n->vfetch, head) {
- LIST_DEL(&vf->head);
- free(vf);
- }
- LIST_FOR_EACH_ENTRY_SAFE(alu, nalu, &n->alu, head) {
- LIST_DEL(&alu->head);
- free(alu);
- }
- free(n);
- }
- free(rshader->bcode);
- return;
-}
-
-int r600_shader_vfetch_bytecode(struct r600_shader *rshader,
- struct r600_shader_node *rnode,
- struct r600_shader_vfetch *vfetch,
- unsigned *cid)
-{
- unsigned id = *cid;
-
- vfetch->cf_addr = id;
- rshader->bcode[id++] = S_SQ_VTX_WORD0_BUFFER_ID(vfetch->src[1].sel) |
- S_SQ_VTX_WORD0_SRC_GPR(vfetch->src[0].sel) |
- S_SQ_VTX_WORD0_SRC_SEL_X(vfetch->src[0].sel) |
- S_SQ_VTX_WORD0_MEGA_FETCH_COUNT(0x1F);
- rshader->bcode[id++] = S_SQ_VTX_WORD1_DST_SEL_X(vfetch->dst[0].chan) |
- S_SQ_VTX_WORD1_DST_SEL_Y(vfetch->dst[1].chan) |
- S_SQ_VTX_WORD1_DST_SEL_Z(vfetch->dst[2].chan) |
- S_SQ_VTX_WORD1_DST_SEL_W(vfetch->dst[3].chan) |
- S_SQ_VTX_WORD1_USE_CONST_FIELDS(1) |
- S_SQ_VTX_WORD1_GPR_DST_GPR(vfetch->dst[0].sel);
- rshader->bcode[id++] = S_SQ_VTX_WORD2_MEGA_FETCH(1);
- rshader->bcode[id++] = 0;
- *cid = id;
- return 0;
-}
-
-int r600_shader_update(struct r600_shader *rshader, enum pipe_format *resource_format)
-{
- struct r600_shader_node *rnode;
- struct r600_shader_vfetch *vfetch;
- unsigned i;
-
- memcpy(rshader->resource_format, resource_format,
- rshader->nresource * sizeof(enum pipe_format));
- LIST_FOR_EACH_ENTRY(rnode, &rshader->nodes, head) {
- LIST_FOR_EACH_ENTRY(vfetch, &rnode->vfetch, head) {
- const struct util_format_description *desc;
- i = vfetch->cf_addr + 1;
- rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_X;
- rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_Y;
- rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_Z;
- rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_W;
- desc = util_format_description(resource_format[vfetch->src[1].sel]);
- if (desc == NULL) {
- fprintf(stderr, "%s unknown format %d\n", __func__, resource_format[vfetch->src[1].sel]);
- continue;
- }
- /* WARNING so far TGSI swizzle match R600 ones */
- rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_X(desc->swizzle[0]);
- rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_Y(desc->swizzle[1]);
- rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_Z(desc->swizzle[2]);
- rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_W(desc->swizzle[3]);
- }
- }
- return 0;
-}
-
-int r600_shader_register(struct r600_shader *rshader)
-{
- struct c_vector *v, *nv;
- unsigned tid, cid, rid, i;
-
- rshader->nvector = rshader->cshader.nvectors;
- rshader->gpr = calloc(rshader->nvector, sizeof(void*));
- if (rshader->gpr == NULL)
- return -ENOMEM;
- tid = 0;
- cid = 0;
- rid = 0;
- /* alloc input first */
- LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[C_FILE_INPUT].vectors, head) {
- nv = c_vector_new();
- if (nv == NULL) {
- return -ENOMEM;
- }
- memcpy(nv, v, sizeof(struct c_vector));
- nv->id = tid++;
- rshader->gpr[v->id] = nv;
- }
- for (i = 0; i < C_FILE_COUNT; i++) {
- if (i == C_FILE_INPUT || i == C_FILE_IMMEDIATE)
- continue;
- LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[i].vectors, head) {
- switch (v->file) {
- case C_FILE_OUTPUT:
- case C_FILE_TEMPORARY:
- nv = c_vector_new();
- if (nv == NULL) {
- return -ENOMEM;
- }
- memcpy(nv, v, sizeof(struct c_vector));
- nv->id = tid++;
- rshader->gpr[v->id] = nv;
- break;
- case C_FILE_CONSTANT:
- nv = c_vector_new();
- if (nv == NULL) {
- return -ENOMEM;
- }
- memcpy(nv, v, sizeof(struct c_vector));
- nv->id = (cid++) + 256;
- rshader->gpr[v->id] = nv;
- break;
- case C_FILE_RESOURCE:
- nv = c_vector_new();
- if (nv == NULL) {
- return -ENOMEM;
- }
- memcpy(nv, v, sizeof(struct c_vector));
- nv->id = (rid++);
- rshader->gpr[v->id] = nv;
- break;
- default:
- fprintf(stderr, "%s:%d unsupported file %d\n", __func__, __LINE__, v->file);
- return -EINVAL;
- }
- }
- }
- rshader->ngpr = tid;
- rshader->nconstant = cid;
- rshader->nresource = rid;
- return 0;
-}
-
-int r600_shader_find_gpr(struct r600_shader *rshader, struct c_vector *v, unsigned swizzle,
- struct r600_shader_operand *operand)
-{
- struct c_vector *tmp;
-
- /* Values [0,127] correspond to GPR[0..127].
- * Values [256,511] correspond to cfile constants c[0..255].
- * Other special values are shown in the list below.
- * 248 SQ_ALU_SRC_0: special constant 0.0.
- * 249 SQ_ALU_SRC_1: special constant 1.0 float.
- * 250 SQ_ALU_SRC_1_INT: special constant 1 integer.
- * 251 SQ_ALU_SRC_M_1_INT: special constant -1 integer.
- * 252 SQ_ALU_SRC_0_5: special constant 0.5 float.
- * 253 SQ_ALU_SRC_LITERAL: literal constant.
- * 254 SQ_ALU_SRC_PV: previous vector result.
- * 255 SQ_ALU_SRC_PS: previous scalar result.
- */
- operand->vector = v;
- operand->sel = 248;
- operand->chan = 0;
- operand->neg = 0;
- operand->abs = 0;
- if (v == NULL)
- return 0;
- if (v->file == C_FILE_IMMEDIATE) {
- operand->sel = 253;
- } else {
- tmp = rshader->gpr[v->id];
- if (tmp == NULL) {
- fprintf(stderr, "%s %d unknown register\n", __FILE__, __LINE__);
- return -EINVAL;
- }
- operand->sel = tmp->id;
- }
- operand->chan = swizzle;
- switch (swizzle) {
- case C_SWIZZLE_X:
- case C_SWIZZLE_Y:
- case C_SWIZZLE_Z:
- case C_SWIZZLE_W:
- break;
- case C_SWIZZLE_0:
- operand->sel = 248;
- operand->chan = 0;
- break;
- case C_SWIZZLE_1:
- operand->sel = 249;
- operand->chan = 0;
- break;
- default:
- fprintf(stderr, "%s %d invalid swizzle %d\n", __FILE__, __LINE__, swizzle);
- return -EINVAL;
- }
- return 0;
-}
-
-static struct r600_shader_node *r600_shader_new_node(struct r600_shader *rshader, struct c_node *node)
-{
- struct r600_shader_node *rnode;
-
- rnode = CALLOC_STRUCT(r600_shader_node);
- if (rnode == NULL)
- return NULL;
- rnode->node = node;
- LIST_INITHEAD(&rnode->vfetch);
-fprintf(stderr, "------------------------ new node (%p %p)\n", &rnode->vfetch, rnode->vfetch.next);
- LIST_INITHEAD(&rnode->alu);
- LIST_ADDTAIL(&rnode->head, &rshader->nodes);
- return rnode;
-}
-
-static int r600_shader_add_vfetch(struct r600_shader *rshader,
- struct r600_shader_node *node,
- struct c_instruction *instruction)
-{
- struct r600_shader_vfetch *vfetch;
- struct r600_shader_node *rnode;
- int r;
-
- if (instruction == NULL)
- return 0;
- if (instruction->op[0].opcode != C_OPCODE_VFETCH)
- return 0;
- if (!LIST_IS_EMPTY(&node->alu)) {
- rnode = r600_shader_new_node(rshader, node->node);
- if (rnode == NULL)
- return -ENOMEM;
- node = rnode;
- }
- vfetch = calloc(1, sizeof(struct r600_shader_vfetch));
- if (vfetch == NULL)
- return -ENOMEM;
- r = r600_shader_find_gpr(rshader, instruction->op[0].output.vector, 0, &vfetch->dst[0]);
- if (r)
- return r;
- r = r600_shader_find_gpr(rshader, instruction->op[0].input[0].vector, 0, &vfetch->src[0]);
- if (r)
- return r;
- r = r600_shader_find_gpr(rshader, instruction->op[0].input[1].vector, 0, &vfetch->src[1]);
- if (r)
- return r;
- vfetch->dst[0].chan = C_SWIZZLE_X;
- vfetch->dst[1].chan = C_SWIZZLE_Y;
- vfetch->dst[2].chan = C_SWIZZLE_Z;
- vfetch->dst[3].chan = C_SWIZZLE_W;
- LIST_ADDTAIL(&vfetch->head, &node->vfetch);
- node->nslot += 2;
- return 0;
-}
-
-static int r600_node_translate(struct r600_shader *rshader, struct c_node *node)
-{
- struct c_instruction *instruction;
- struct r600_shader_node *rnode;
- int r;
-
- rnode = r600_shader_new_node(rshader, node);
- if (rnode == NULL)
- return -ENOMEM;
- LIST_FOR_EACH_ENTRY(instruction, &node->insts, head) {
- switch (instruction->op[0].opcode) {
- case C_OPCODE_VFETCH:
- r = r600_shader_add_vfetch(rshader, rnode, instruction);
- if (r) {
- fprintf(stderr, "%s %d vfetch failed\n", __func__, __LINE__);
- return r;
- }
- break;
- default:
- r = r600_shader_alu_translate(rshader, rnode, instruction);
- if (r) {
- fprintf(stderr, "%s %d alu failed\n", __func__, __LINE__);
- return r;
- }
- break;
- }
- }
- return 0;
-}
-
-int r600_shader_translate_rec(struct r600_shader *rshader, struct c_node *node)
-{
- struct c_node_link *link;
- int r;
-
- if (node->opcode == C_OPCODE_END)
- return 0;
- r = r600_node_translate(rshader, node);
- if (r)
- return r;
- LIST_FOR_EACH_ENTRY(link, &node->childs, head) {
- r = r600_shader_translate_rec(rshader, link->node);
- if (r)
- return r;
- }
- return 0;
-}
-
-static struct r600_shader_alu *r600_shader_insert_alu(struct r600_shader *rshader, struct r600_shader_node *node)
-{
- struct r600_shader_alu *alu;
-
- alu = CALLOC_STRUCT(r600_shader_alu);
- if (alu == NULL)
- return NULL;
- alu->alu[0].inst = INST_NOP;
- alu->alu[1].inst = INST_NOP;
- alu->alu[2].inst = INST_NOP;
- alu->alu[3].inst = INST_NOP;
- alu->alu[4].inst = INST_NOP;
- alu->alu[0].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
- alu->alu[1].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
- alu->alu[2].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
- alu->alu[3].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
- alu->alu[4].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
- alu->alu[1].dst.chan = 1;
- alu->alu[2].dst.chan = 2;
- alu->alu[3].dst.chan = 3;
- LIST_ADDTAIL(&alu->head, &node->alu);
- return alu;
-}
-
-static int r600_shader_alu_translate(struct r600_shader *rshader,
- struct r600_shader_node *node,
- struct c_instruction *instruction)
-{
- struct r600_shader_node *rnode;
- struct r600_shader_alu *alu;
- int i, j, r, litteral_lastcomp = -1;
-
- if (!LIST_IS_EMPTY(&node->vfetch)) {
-fprintf(stderr, "------------------------ add node (%p %p)\n", &node->vfetch, node->vfetch.next);
- rnode = r600_shader_new_node(rshader, node->node);
- if (rnode == NULL) {
- fprintf(stderr, "%s %d new node failed\n", __func__, __LINE__);
- return -ENOMEM;
- }
- node = rnode;
- }
-
- /* initialize alu */
- alu = r600_shader_insert_alu(rshader, node);
-
- /* check special operation like lit */
-
- /* go through operation */
- for (i = 0; i < instruction->nop; i++) {
- struct r600_alu_instruction *ainfo = &r600_alu_instruction[instruction->op[i].opcode];
- struct r600_instruction_info *iinfo = &r600_instruction_info[ainfo->instruction];
- unsigned comp;
-
- /* check that output is a valid component */
- comp = instruction->op[i].output.swizzle;
- switch (comp) {
- case C_SWIZZLE_X:
- case C_SWIZZLE_Y:
- case C_SWIZZLE_Z:
- case C_SWIZZLE_W:
- break;
- case C_SWIZZLE_0:
- case C_SWIZZLE_1:
- default:
- fprintf(stderr, "%s %d invalid output %d\n", __func__, __LINE__, comp);
- return -EINVAL;
- }
- alu->alu[comp].inst = ainfo->instruction;
- alu->alu[comp].opcode = iinfo->opcode;
- alu->alu[comp].is_op3 = iinfo->is_op3;
- for (j = 0; j < instruction->op[i].ninput; j++) {
- r = r600_shader_find_gpr(rshader, instruction->op[i].input[j].vector,
- instruction->op[i].input[j].swizzle, &alu->alu[comp].src[j]);
- if (r) {
- fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__);
- return r;
- }
- if (instruction->op[i].input[j].vector->file == C_FILE_IMMEDIATE) {
- r = instruction->op[i].input[j].swizzle;
- switch (r) {
- case C_SWIZZLE_X:
- case C_SWIZZLE_Y:
- case C_SWIZZLE_Z:
- case C_SWIZZLE_W:
- break;
- case C_SWIZZLE_0:
- case C_SWIZZLE_1:
- default:
- fprintf(stderr, "%s %d invalid input\n", __func__, __LINE__);
- return -EINVAL;
- }
- alu->literal[r] = instruction->op[i].input[j].vector->channel[r]->value;
- if (r > litteral_lastcomp) {
- litteral_lastcomp = r;
- }
- }
- }
- r = r600_shader_find_gpr(rshader, instruction->op[i].output.vector,
- instruction->op[i].output.swizzle, &alu->alu[comp].dst);
- if (r) {
- fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__);
- return r;
- }
- }
- switch (litteral_lastcomp) {
- case 0:
- case 1:
- alu->nliteral = 2;
- break;
- case 2:
- case 3:
- alu->nliteral = 4;
- break;
- case -1:
- default:
- break;
- }
- for (i = 4; i >= 0; i--) {
- if (alu->alu[i].inst != INST_NOP) {
- alu->alu[i].last = 1;
- alu->nalu = i + 1;
- break;
- }
- }
- return 0;
-}
-
-void r600_shader_node_place(struct r600_shader *rshader)
-{
- struct r600_shader_node *node, *nnode;
- struct r600_shader_alu *alu, *nalu;
- struct r600_shader_vfetch *vfetch, *nvfetch;
- unsigned cf_id = 0, cf_addr = 0;
-
- rshader->ncf = 0;
- rshader->nslot = 0;
- LIST_FOR_EACH_ENTRY_SAFE(node, nnode, &rshader->nodes, head) {
- LIST_FOR_EACH_ENTRY_SAFE(alu, nalu, &node->alu, head) {
- node->nslot += alu->nalu;
- node->nslot += alu->nliteral >> 1;
- }
- node->nfetch = 0;
- LIST_FOR_EACH_ENTRY_SAFE(vfetch, nvfetch, &node->vfetch, head) {
- node->nslot += 2;
- node->nfetch += 1;
- }
- if (!LIST_IS_EMPTY(&node->vfetch)) {
- /* fetch node need to be 16 bytes aligned*/
- cf_addr += 1;
- cf_addr &= 0xFFFFFFFEUL;
- }
- node->cf_id = cf_id;
- node->cf_addr = cf_addr;
- cf_id += 2;
- cf_addr += node->nslot * 2;
- rshader->ncf++;
- }
- rshader->nslot = cf_addr;
- LIST_FOR_EACH_ENTRY_SAFE(node, nnode, &rshader->nodes, head) {
- node->cf_addr += cf_id * 2;
- }
- rshader->ncf += rshader->cshader.files[C_FILE_OUTPUT].nvectors;
- rshader->ndw = rshader->ncf * 2 + rshader->nslot * 2;
-}
-
-int r600_shader_legalize(struct r600_shader *rshader)
-{
- return 0;
-}
-
-
-static int r600_cshader_legalize_rec(struct c_shader *shader, struct c_node *node)
-{
- struct c_node_link *link;
- struct c_instruction *i, *n;
- struct c_operand operand;
- unsigned k, inst;
- int r;
-
- LIST_FOR_EACH_ENTRY(i, &node->insts, head) {
- for (k = 0; k < i->nop; k++) {
- switch (i->op[k].opcode) {
- case C_OPCODE_SLT:
- i->op[k].opcode = C_OPCODE_SGT;
- memcpy(&operand, &i->op[k].input[0], sizeof(struct c_operand));
- memcpy(&i->op[k].input[0], &i->op[k].input[1], sizeof(struct c_operand));
- memcpy(&i->op[k].input[1], &operand, sizeof(struct c_operand));
- break;
- default:
- break;
- }
- inst = r600_alu_instruction[i->op[k].opcode].instruction;
- if (r600_instruction_info[inst].is_trans && k < (i->nop -1)) {
- /* split trans opcode */
- n = CALLOC_STRUCT(c_instruction);
- if (n == NULL)
- return -ENOMEM;
- for (n->nop = 0, k = k + 1; k < i->nop; k++, n->nop++) {
- memcpy(&n->op[n->nop - 0], &i->op[k], sizeof(struct c_op));
- }
- i->nop -= n->nop;
- LIST_ADD(&n->head, &i->head);
- }
- }
- }
- LIST_FOR_EACH_ENTRY(link, &node->childs, head) {
- r = r600_cshader_legalize_rec(shader, link->node);
- if (r) {
- return r;
- }
- }
- return 0;
-}
-
-int r600_cshader_legalize(struct c_shader *shader)
-{
- return r600_cshader_legalize_rec(shader, &shader->entry);
-}
-
-
-struct r600_instruction_info r600_instruction_info[] = {
- {INST_ADD, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD, 0, 0},
- {INST_MUL, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL, 0, 0},
- {INST_MUL_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL_IEEE, 0, 0},
- {INST_MAX, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX, 0, 0},
- {INST_MIN, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN, 0, 0},
- {INST_MAX_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX_DX10, 0, 0},
- {INST_MIN_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN_DX10, 0, 0},
- {INST_SETE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETE, 0, 0},
- {INST_SETGT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT, 0, 0},
- {INST_SETGE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE, 0, 0},
- {INST_SETNE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETNE, 0, 0},
- {INST_SETE_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETE_DX10, 0, 0},
- {INST_SETGT_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT_DX10, 0, 0},
- {INST_SETGE_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE_DX10, 0, 0},
- {INST_SETNE_DX10, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETNE_DX10, 0, 0},
- {INST_FRACT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT, 0, 0},
- {INST_TRUNC, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_TRUNC, 0, 0},
- {INST_CEIL, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CEIL, 0, 0},
- {INST_RNDNE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RNDNE, 0, 0},
- {INST_FLOOR, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR, 0, 0},
- {INST_MOVA, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA, 0, 0},
- {INST_MOVA_FLOOR, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR, 0, 0},
- {INST_MOVA_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_INT, 0, 0},
- {INST_MOV, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV, 0, 0},
- {INST_NOP, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, 0, 0},
- {INST_PRED_SETGT_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_UINT, 0, 0},
- {INST_PRED_SETGE_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_UINT, 0, 0},
- {INST_PRED_SETE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE, 0, 0},
- {INST_PRED_SETGT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT, 0, 0},
- {INST_PRED_SETGE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE, 0, 0},
- {INST_PRED_SETNE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE, 0, 0},
- {INST_PRED_SET_INV, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_INV, 0, 0},
- {INST_PRED_SET_POP, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_POP, 0, 0},
- {INST_PRED_SET_CLR, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_CLR, 0, 0},
- {INST_PRED_SET_RESTORE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_RESTORE, 0, 0},
- {INST_PRED_SETE_PUSH, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_PUSH, 0, 0},
- {INST_PRED_SETGT_PUSH, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_PUSH, 0, 0},
- {INST_PRED_SETGE_PUSH, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_PUSH, 0, 0},
- {INST_PRED_SETNE_PUSH, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_PUSH, 0, 0},
- {INST_KILLE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE, 0, 0},
- {INST_KILLGT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT, 0, 0},
- {INST_KILLGE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE, 0, 0},
- {INST_KILLNE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLNE, 0, 0},
- {INST_AND_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_AND_INT, 0, 0},
- {INST_OR_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_OR_INT, 0, 0},
- {INST_XOR_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_XOR_INT, 0, 0},
- {INST_NOT_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOT_INT, 0, 0},
- {INST_ADD_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD_INT, 0, 0},
- {INST_SUB_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SUB_INT, 0, 0},
- {INST_MAX_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX_INT, 0, 0},
- {INST_MIN_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN_INT, 0, 0},
- {INST_MAX_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX_UINT, 0, 0},
- {INST_MIN_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN_UINT, 0, 0},
- {INST_SETE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETE_INT, 0, 0},
- {INST_SETGT_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT_INT, 0, 0},
- {INST_SETGE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE_INT, 0, 0},
- {INST_SETNE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETNE_INT, 0, 0},
- {INST_SETGT_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT_UINT, 0, 0},
- {INST_SETGE_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE_UINT, 0, 0},
- {INST_KILLGT_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT_UINT, 0, 0},
- {INST_KILLGE_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE_UINT, 0, 0},
- {INST_PRED_SETE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_INT, 0, 0},
- {INST_PRED_SETGT_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_INT, 0, 0},
- {INST_PRED_SETGE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_INT, 0, 0},
- {INST_PRED_SETNE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_INT, 0, 0},
- {INST_KILLE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE_INT, 0, 0},
- {INST_KILLGT_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT_INT, 0, 0},
- {INST_KILLGE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE_INT, 0, 0},
- {INST_KILLNE_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLNE_INT, 0, 0},
- {INST_PRED_SETE_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_PUSH_INT, 0, 0},
- {INST_PRED_SETGT_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_PUSH_INT, 0, 0},
- {INST_PRED_SETGE_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_PUSH_INT, 0, 0},
- {INST_PRED_SETNE_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_PUSH_INT, 0, 0},
- {INST_PRED_SETLT_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETLT_PUSH_INT, 0, 0},
- {INST_PRED_SETLE_PUSH_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETLE_PUSH_INT, 0, 0},
- {INST_DOT4, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, 0, 0},
- {INST_DOT4_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4_IEEE, 0, 0},
- {INST_CUBE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE, 0, 0},
- {INST_MAX4, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX4, 0, 0},
- {INST_MOVA_GPR_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_GPR_INT, 0, 0},
- {INST_EXP_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE, 1, 0},
- {INST_LOG_CLAMPED, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_CLAMPED, 1, 0},
- {INST_LOG_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE, 1, 0},
- {INST_RECIP_CLAMPED, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_CLAMPED, 1, 0},
- {INST_RECIP_FF, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_FF, 1, 0},
- {INST_RECIP_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE, 1, 0},
- {INST_RECIPSQRT_CLAMPED, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_CLAMPED, 1, 0},
- {INST_RECIPSQRT_FF, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_FF, 1, 0},
- {INST_RECIPSQRT_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_IEEE, 1, 0},
- {INST_SQRT_IEEE, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SQRT_IEEE, 1, 0},
- {INST_FLT_TO_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT, 1, 0},
- {INST_INT_TO_FLT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INT_TO_FLT, 1, 0},
- {INST_UINT_TO_FLT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_UINT_TO_FLT, 1, 0},
- {INST_SIN, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN, 1, 0},
- {INST_COS, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS, 1, 0},
- {INST_ASHR_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ASHR_INT, 1, 0},
- {INST_LSHR_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHR_INT, 1, 0},
- {INST_LSHL_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHL_INT, 1, 0},
- {INST_MULLO_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULLO_INT, 1, 0},
- {INST_MULHI_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULHI_INT, 1, 0},
- {INST_MULLO_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULLO_UINT, 1, 0},
- {INST_MULHI_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULHI_UINT, 1, 0},
- {INST_RECIP_INT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_INT, 1, 0},
- {INST_RECIP_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_UINT, 1, 0},
- {INST_FLT_TO_UINT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_UINT, 1, 0},
- {INST_MUL_LIT, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT, 1, 1},
- {INST_MUL_LIT_M2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT_M2, 1, 1},
- {INST_MUL_LIT_M4, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT_M4, 1, 1},
- {INST_MUL_LIT_D2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT_D2, 1, 1},
- {INST_MULADD, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD, 0, 1},
- {INST_MULADD_M2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_M2, 0, 1},
- {INST_MULADD_M4, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_M4, 0, 1},
- {INST_MULADD_D2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_D2, 0, 1},
- {INST_MULADD_IEEE, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_IEEE, 0, 1},
- {INST_MULADD_IEEE_M2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_IEEE_M2, 0, 1},
- {INST_MULADD_IEEE_M4, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_IEEE_M4, 0, 1},
- {INST_MULADD_IEEE_D2, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD_IEEE_D2, 0, 1},
- {INST_CNDE, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDE, 0, 1},
- {INST_CNDGT, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGT, 0, 1},
- {INST_CNDGE, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGE, 0, 1},
- {INST_CNDE_INT, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDE_INT, 0, 1},
- {INST_CNDGT_INT, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGT_INT, 0, 1},
- {INST_CNDGE_INT, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGE_INT, 0, 1},
-};
-
-struct r600_alu_instruction r600_alu_instruction[C_OPCODE_LAST] = {
- {C_OPCODE_NOP, INST_NOP},
- {C_OPCODE_MOV, INST_MOV},
- {C_OPCODE_LIT, INST_NOP},
- {C_OPCODE_RCP, INST_RECIP_IEEE},
- {C_OPCODE_RSQ, INST_RECIPSQRT_IEEE},
- {C_OPCODE_EXP, INST_EXP_IEEE},
- {C_OPCODE_LOG, INST_LOG_IEEE},
- {C_OPCODE_MUL, INST_MUL},
- {C_OPCODE_ADD, INST_ADD},
- {C_OPCODE_DP3, INST_DOT4},
- {C_OPCODE_DP4, INST_DOT4},
- {C_OPCODE_DST, INST_NOP},
- {C_OPCODE_MIN, INST_MIN},
- {C_OPCODE_MAX, INST_MAX},
- {C_OPCODE_SLT, INST_NOP},
- {C_OPCODE_SGE, INST_NOP},
- {C_OPCODE_MAD, INST_MULADD},
- {C_OPCODE_SUB, INST_COUNT},
- {C_OPCODE_LRP, INST_NOP},
- {C_OPCODE_CND, INST_NOP},
- {20, INST_NOP},
- {C_OPCODE_DP2A, INST_NOP},
- {22, INST_NOP},
- {23, INST_NOP},
- {C_OPCODE_FRC, INST_NOP},
- {C_OPCODE_CLAMP, INST_NOP},
- {C_OPCODE_FLR, INST_NOP},
- {C_OPCODE_ROUND, INST_NOP},
- {C_OPCODE_EX2, INST_NOP},
- {C_OPCODE_LG2, INST_NOP},
- {C_OPCODE_POW, INST_NOP},
- {C_OPCODE_XPD, INST_NOP},
- {32, INST_NOP},
- {C_OPCODE_ABS, INST_COUNT},
- {C_OPCODE_RCC, INST_NOP},
- {C_OPCODE_DPH, INST_NOP},
- {C_OPCODE_COS, INST_COS},
- {C_OPCODE_DDX, INST_NOP},
- {C_OPCODE_DDY, INST_NOP},
- {C_OPCODE_KILP, INST_NOP},
- {C_OPCODE_PK2H, INST_NOP},
- {C_OPCODE_PK2US, INST_NOP},
- {C_OPCODE_PK4B, INST_NOP},
- {C_OPCODE_PK4UB, INST_NOP},
- {C_OPCODE_RFL, INST_NOP},
- {C_OPCODE_SEQ, INST_NOP},
- {C_OPCODE_SFL, INST_NOP},
- {C_OPCODE_SGT, INST_SETGT},
- {C_OPCODE_SIN, INST_SIN},
- {C_OPCODE_SLE, INST_NOP},
- {C_OPCODE_SNE, INST_NOP},
- {C_OPCODE_STR, INST_NOP},
- {C_OPCODE_TEX, INST_NOP},
- {C_OPCODE_TXD, INST_NOP},
- {C_OPCODE_TXP, INST_NOP},
- {C_OPCODE_UP2H, INST_NOP},
- {C_OPCODE_UP2US, INST_NOP},
- {C_OPCODE_UP4B, INST_NOP},
- {C_OPCODE_UP4UB, INST_NOP},
- {C_OPCODE_X2D, INST_NOP},
- {C_OPCODE_ARA, INST_NOP},
- {C_OPCODE_ARR, INST_NOP},
- {C_OPCODE_BRA, INST_NOP},
- {C_OPCODE_CAL, INST_NOP},
- {C_OPCODE_RET, INST_NOP},
- {C_OPCODE_SSG, INST_NOP},
- {C_OPCODE_CMP, INST_NOP},
- {C_OPCODE_SCS, INST_NOP},
- {C_OPCODE_TXB, INST_NOP},
- {C_OPCODE_NRM, INST_NOP},
- {C_OPCODE_DIV, INST_NOP},
- {C_OPCODE_DP2, INST_NOP},
- {C_OPCODE_TXL, INST_NOP},
- {C_OPCODE_BRK, INST_NOP},
- {C_OPCODE_IF, INST_NOP},
- {C_OPCODE_BGNFOR, INST_NOP},
- {C_OPCODE_REP, INST_NOP},
- {C_OPCODE_ELSE, INST_NOP},
- {C_OPCODE_ENDIF, INST_NOP},
- {C_OPCODE_ENDFOR, INST_NOP},
- {C_OPCODE_ENDREP, INST_NOP},
- {C_OPCODE_PUSHA, INST_NOP},
- {C_OPCODE_POPA, INST_NOP},
- {C_OPCODE_CEIL, INST_NOP},
- {C_OPCODE_I2F, INST_NOP},
- {C_OPCODE_NOT, INST_NOP},
- {C_OPCODE_TRUNC, INST_NOP},
- {C_OPCODE_SHL, INST_NOP},
- {88, INST_NOP},
- {C_OPCODE_AND, INST_NOP},
- {C_OPCODE_OR, INST_NOP},
- {C_OPCODE_MOD, INST_NOP},
- {C_OPCODE_XOR, INST_NOP},
- {C_OPCODE_SAD, INST_NOP},
- {C_OPCODE_TXF, INST_NOP},
- {C_OPCODE_TXQ, INST_NOP},
- {C_OPCODE_CONT, INST_NOP},
- {C_OPCODE_EMIT, INST_NOP},
- {C_OPCODE_ENDPRIM, INST_NOP},
- {C_OPCODE_BGNLOOP, INST_NOP},
- {C_OPCODE_BGNSUB, INST_NOP},
- {C_OPCODE_ENDLOOP, INST_NOP},
- {C_OPCODE_ENDSUB, INST_NOP},
- {103, INST_NOP},
- {104, INST_NOP},
- {105, INST_NOP},
- {106, INST_NOP},
- {107, INST_NOP},
- {108, INST_NOP},
- {109, INST_NOP},
- {110, INST_NOP},
- {111, INST_NOP},
- {C_OPCODE_NRM4, INST_NOP},
- {C_OPCODE_CALLNZ, INST_NOP},
- {C_OPCODE_IFC, INST_NOP},
- {C_OPCODE_BREAKC, INST_NOP},
- {C_OPCODE_KIL, INST_NOP},
- {C_OPCODE_END, INST_NOP},
- {118, INST_NOP},
- {C_OPCODE_F2I, INST_NOP},
- {C_OPCODE_IDIV, INST_NOP},
- {C_OPCODE_IMAX, INST_NOP},
- {C_OPCODE_IMIN, INST_NOP},
- {C_OPCODE_INEG, INST_NOP},
- {C_OPCODE_ISGE, INST_NOP},
- {C_OPCODE_ISHR, INST_NOP},
- {C_OPCODE_ISLT, INST_NOP},
- {C_OPCODE_F2U, INST_NOP},
- {C_OPCODE_U2F, INST_NOP},
- {C_OPCODE_UADD, INST_NOP},
- {C_OPCODE_UDIV, INST_NOP},
- {C_OPCODE_UMAD, INST_NOP},
- {C_OPCODE_UMAX, INST_NOP},
- {C_OPCODE_UMIN, INST_NOP},
- {C_OPCODE_UMOD, INST_NOP},
- {C_OPCODE_UMUL, INST_NOP},
- {C_OPCODE_USEQ, INST_NOP},
- {C_OPCODE_USGE, INST_NOP},
- {C_OPCODE_USHR, INST_NOP},
- {C_OPCODE_USLT, INST_NOP},
- {C_OPCODE_USNE, INST_NOP},
- {C_OPCODE_SWITCH, INST_NOP},
- {C_OPCODE_CASE, INST_NOP},
- {C_OPCODE_DEFAULT, INST_NOP},
- {C_OPCODE_ENDSWITCH, INST_NOP},
- {C_OPCODE_VFETCH, INST_NOP},
- {C_OPCODE_ENTRY, INST_NOP},
- {C_OPCODE_ARL, INST_NOP},
-};
-
-
-static int r600_shader_alu_bytecode(struct r600_shader *rshader,
- struct r600_shader_node *rnode,
- struct r600_shader_inst *alu,
- unsigned *cid)
-{
- unsigned id = *cid;
-
- /* don't replace gpr by pv or ps for destination register */
- if (alu->is_op3) {
- rshader->bcode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
- S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
- S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
- S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
- S_SQ_ALU_WORD0_LAST(alu->last);
- rshader->bcode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
- S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
- S_SQ_ALU_WORD1_OP3_SRC2_SEL(alu->src[2].sel) |
- S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) |
- S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) |
- S_SQ_ALU_WORD1_OP3_ALU_INST(alu->opcode) |
- S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
- } else {
- rshader->bcode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
- S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
- S_SQ_ALU_WORD0_SRC0_NEG(alu->src[0].neg) |
- S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
- S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
- S_SQ_ALU_WORD0_SRC1_NEG(alu->src[1].neg) |
- S_SQ_ALU_WORD0_LAST(alu->last);
- rshader->bcode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
- S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
- S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) |
- S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) |
- S_SQ_ALU_WORD1_OP2_WRITE_MASK(1) |
- S_SQ_ALU_WORD1_OP2_ALU_INST(alu->opcode) |
- S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
- }
- *cid = id;
- return 0;
-}
-
-int r6xx_shader_alu_translate(struct r600_shader *rshader,
- struct r600_shader_node *rnode,
- unsigned *cid)
-{
- struct r600_shader_alu *alu;
- unsigned id = *cid;
- int i;
- int r = 0;
- LIST_FOR_EACH_ENTRY(alu, &rnode->alu, head) {
- for (i = 0; i < alu->nalu; i++) {
- r = r600_shader_alu_bytecode(rshader, rnode, &alu->alu[i], &id);
- if (r)
- goto out;
- }
- for (i = 0; i < alu->nliteral; i++) {
- rshader->bcode[id++] = alu->literal[i];
- }
- }
-out:
- *cid = id;
- return r;
-}
diff --git a/src/gallium/drivers/r600/r600_compiler_r700.c b/src/gallium/drivers/r600/r600_compiler_r700.c
deleted file mode 100644
index 0b43942866..0000000000
--- a/src/gallium/drivers/r600/r600_compiler_r700.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright 2010 Jerome Glisse <glisse@freedesktop.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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <errno.h>
-#include "r600_context.h"
-#include "r700_sq.h"
-
-static int r700_shader_cf_node_bytecode(struct r600_shader *rshader,
- struct r600_shader_node *rnode,
- unsigned *cid)
-{
- unsigned id = *cid;
-
- if (rnode->nfetch) {
- rshader->bcode[id++] = S_SQ_CF_WORD0_ADDR(rnode->cf_addr >> 1);
- rshader->bcode[id++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX) |
- S_SQ_CF_WORD1_BARRIER(1) |
- S_SQ_CF_WORD1_COUNT(rnode->nfetch - 1);
- } else {
- rshader->bcode[id++] = S_SQ_CF_ALU_WORD0_ADDR(rnode->cf_addr >> 1);
- rshader->bcode[id++] = S_SQ_CF_ALU_WORD1_CF_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU) |
- S_SQ_CF_ALU_WORD1_BARRIER(1) |
- S_SQ_CF_ALU_WORD1_COUNT(rnode->nslot - 1);
- }
- *cid = id;
- return 0;
-}
-
-static int r700_shader_cf_output_bytecode(struct r600_shader *rshader,
- struct c_vector *v,
- unsigned *cid,
- unsigned end)
-{
- struct r600_shader_operand out;
- unsigned id = *cid;
- int r;
-
- r = r600_shader_find_gpr(rshader, v, 0, &out);
- if (r)
- return r;
- rshader->bcode[id + 0] = S_SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR(out.sel) |
- S_SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE(3);
- rshader->bcode[id + 1] = S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X(0) |
- S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y(1) |
- S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z(2) |
- S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W(3) |
- S_SQ_CF_ALLOC_EXPORT_WORD1_BARRIER(1) |
- S_SQ_CF_ALLOC_EXPORT_WORD1_CF_INST(V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE) |
- S_SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM(end);
- switch (v->name) {
- case C_SEMANTIC_POSITION:
- rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(60) |
- S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS);
- break;
- case C_SEMANTIC_COLOR:
- if (rshader->cshader.type == C_PROGRAM_TYPE_VS) {
- rshader->output[rshader->noutput].gpr = out.sel;
- rshader->output[rshader->noutput].sid = v->sid;
- rshader->output[rshader->noutput].name = v->name;
- rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(rshader->noutput++) |
- S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM);
- } else {
- rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(0) |
- S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL);
- }
- break;
- case C_SEMANTIC_GENERIC:
- rshader->output[rshader->noutput].gpr = out.sel;
- rshader->output[rshader->noutput].sid = v->sid;
- rshader->output[rshader->noutput].name = v->name;
- rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(rshader->noutput++) |
- S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM);
- break;
- default:
- fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- *cid = id + 2;
- return 0;
-}
-
-static int r700_shader_alu_bytecode(struct r600_shader *rshader,
- struct r600_shader_node *rnode,
- struct r600_shader_inst *alu,
- unsigned *cid)
-{
- unsigned id = *cid;
-
- /* don't replace gpr by pv or ps for destination register */
- if (alu->is_op3) {
- rshader->bcode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
- S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
- S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
- S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
- S_SQ_ALU_WORD0_LAST(alu->last);
- rshader->bcode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
- S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
- S_SQ_ALU_WORD1_OP3_SRC2_SEL(alu->src[2].sel) |
- S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) |
- S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) |
- S_SQ_ALU_WORD1_OP3_ALU_INST(alu->opcode) |
- S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
- } else {
- rshader->bcode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
- S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
- S_SQ_ALU_WORD0_SRC0_NEG(alu->src[0].neg) |
- S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
- S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
- S_SQ_ALU_WORD0_SRC1_NEG(alu->src[1].neg) |
- S_SQ_ALU_WORD0_LAST(alu->last);
- rshader->bcode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
- S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
- S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) |
- S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) |
- S_SQ_ALU_WORD1_OP2_WRITE_MASK(1) |
- S_SQ_ALU_WORD1_OP2_ALU_INST(alu->opcode) |
- S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
- }
- *cid = id;
- return 0;
-}
-
-static int r700_shader_alu_translate(struct r600_shader *rshader,
- struct r600_shader_node *rnode,
- unsigned *cid)
-
-{
- struct r600_shader_alu *alu;
- unsigned id = *cid;
- int i;
- int r = 0;
- LIST_FOR_EACH_ENTRY(alu, &rnode->alu, head) {
- for (i = 0; i < alu->nalu; i++) {
- r = r700_shader_alu_bytecode(rshader, rnode, &alu->alu[i], &id);
- if (r)
- goto out;
- }
- for (i = 0; i < alu->nliteral; i++) {
- rshader->bcode[id++] = alu->literal[i];
- }
- }
- out:
- *cid = id;
- return r;
-}
-
-int r700_shader_translate(struct r600_shader *rshader)
-{
- struct c_shader *shader = &rshader->cshader;
- struct r600_shader_node *rnode;
- struct r600_shader_vfetch *vfetch;
- struct c_vector *v;
- unsigned id, end;
- int r;
-
- r = r600_shader_register(rshader);
- if (r) {
- fprintf(stderr, "%s %d register allocation failed\n", __FILE__, __LINE__);
- return r;
- }
- r = r600_shader_translate_rec(rshader, &shader->entry);
- if (r) {
- fprintf(stderr, "%s %d translation failed\n", __FILE__, __LINE__);
- return r;
- }
- r = r600_shader_legalize(rshader);
- if (r) {
- fprintf(stderr, "%s %d legalize failed\n", __FILE__, __LINE__);
- return r;
- }
- r600_shader_node_place(rshader);
- rshader->bcode = malloc(rshader->ndw * 4);
- if (rshader->bcode == NULL)
- return -ENOMEM;
- LIST_FOR_EACH_ENTRY(rnode, &rshader->nodes, head) {
- id = rnode->cf_addr;
- LIST_FOR_EACH_ENTRY(vfetch, &rnode->vfetch, head) {
- r = r600_shader_vfetch_bytecode(rshader, rnode, vfetch, &id);
- if (r)
- return r;
- }
- if (rshader->r6xx_compile)
- r = r6xx_shader_alu_translate(rshader, rnode, &id);
- else
- r = r700_shader_alu_translate(rshader, rnode, &id);
- if (r)
- return r;
- }
- id = 0;
- LIST_FOR_EACH_ENTRY(rnode, &rshader->nodes, head) {
- r = r700_shader_cf_node_bytecode(rshader, rnode, &id);
- if (r)
- return r;
- }
- LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[C_FILE_OUTPUT].vectors, head) {
- end = 0;
- if (v->head.next == &rshader->cshader.files[C_FILE_OUTPUT].vectors)
- end = 1;
- r = r700_shader_cf_output_bytecode(rshader, v, &id, end);
- if (r)
- return r;
- }
- LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[C_FILE_INPUT].vectors, head) {
- rshader->input[rshader->ninput].gpr = rshader->ninput;
- rshader->input[rshader->ninput].sid = v->sid;
- rshader->input[rshader->ninput].name = v->name;
- rshader->ninput++;
- }
- return 0;
-}
diff --git a/src/gallium/drivers/r600/r600_compiler_tgsi.c b/src/gallium/drivers/r600/r600_compiler_tgsi.c
deleted file mode 100644
index 172cf154a3..0000000000
--- a/src/gallium/drivers/r600/r600_compiler_tgsi.c
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright 2010 Jerome Glisse <glisse@freedesktop.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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <errno.h>
-#include <tgsi/tgsi_parse.h>
-#include <tgsi/tgsi_scan.h>
-#include "r600_shader.h"
-#include "r600_context.h"
-
-struct tgsi_shader {
- struct c_vector **v[TGSI_FILE_COUNT];
- struct tgsi_shader_info info;
- struct tgsi_parse_context parser;
- const struct tgsi_token *tokens;
- struct c_shader *shader;
- struct c_node *node;
-};
-
-static unsigned tgsi_file_to_c_file(unsigned file);
-static unsigned tgsi_sname_to_c_sname(unsigned sname);
-static int tgsi_opcode_to_c_opcode(unsigned opcode, unsigned *copcode);
-
-static int tgsi_shader_init(struct tgsi_shader *ts,
- const struct tgsi_token *tokens,
- struct c_shader *shader)
-{
- int i;
-
- ts->shader = shader;
- ts->tokens = tokens;
- tgsi_scan_shader(ts->tokens, &ts->info);
- tgsi_parse_init(&ts->parser, ts->tokens);
- /* initialize to NULL in case of error */
- for (i = 0; i < C_FILE_COUNT; i++) {
- ts->v[i] = NULL;
- }
- for (i = 0; i < TGSI_FILE_COUNT; i++) {
- if (ts->info.file_count[i] > 0) {
- ts->v[i] = calloc(ts->info.file_count[i], sizeof(void*));
- if (ts->v[i] == NULL) {
- fprintf(stderr, "%s:%d unsupported %d %d\n", __func__, __LINE__, i, ts->info.file_count[i]);
- return -ENOMEM;
- }
- }
- }
- return 0;
-}
-
-static void tgsi_shader_destroy(struct tgsi_shader *ts)
-{
- int i;
-
- for (i = 0; i < TGSI_FILE_COUNT; i++) {
- free(ts->v[i]);
- }
- tgsi_parse_free(&ts->parser);
-}
-
-static int ntransform_declaration(struct tgsi_shader *ts)
-{
- struct tgsi_full_declaration *fd = &ts->parser.FullToken.FullDeclaration;
- struct c_vector *v;
- unsigned file;
- unsigned name;
- int sid;
- int i;
-
- if (fd->Declaration.Dimension) {
- fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- for (i = fd->Range.First ; i <= fd->Range.Last; i++) {
- sid = i;
- name = C_SEMANTIC_GENERIC;
- file = tgsi_file_to_c_file(fd->Declaration.File);
- if (file == TGSI_FILE_NULL) {
- fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- if (fd->Declaration.Semantic) {
- name = tgsi_sname_to_c_sname(fd->Semantic.Name);
- sid = fd->Semantic.Index;
- }
- v = c_shader_vector_new(ts->shader, file, name, sid);
- if (v == NULL) {
- fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
- return -ENOMEM;
- }
- ts->v[fd->Declaration.File][i] = v;
- }
- return 0;
-}
-
-static int ntransform_immediate(struct tgsi_shader *ts)
-{
- struct tgsi_full_immediate *fd = &ts->parser.FullToken.FullImmediate;
- struct c_vector *v;
- unsigned file;
- unsigned name;
-
- if (fd->Immediate.DataType != TGSI_IMM_FLOAT32) {
- fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- name = C_SEMANTIC_GENERIC;
- file = C_FILE_IMMEDIATE;
- v = c_shader_vector_new(ts->shader, file, name, 0);
- if (v == NULL) {
- fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
- return -ENOMEM;
- }
- v->channel[0]->value = fd->u[0].Uint;
- v->channel[1]->value = fd->u[1].Uint;
- v->channel[2]->value = fd->u[2].Uint;
- v->channel[3]->value = fd->u[3].Uint;
- ts->v[TGSI_FILE_IMMEDIATE][0] = v;
- return 0;
-}
-
-static int ntransform_instruction(struct tgsi_shader *ts)
-{
- struct tgsi_full_instruction *fi = &ts->parser.FullToken.FullInstruction;
- struct c_shader *shader = ts->shader;
- struct c_instruction instruction;
- unsigned opcode;
- int i, j, r;
-
- if (fi->Instruction.NumDstRegs > 1) {
- fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- if (fi->Instruction.Saturate) {
- fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- if (fi->Instruction.Predicate) {
- fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- if (fi->Instruction.Label) {
- fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- if (fi->Instruction.Texture) {
- fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- for (i = 0; i < fi->Instruction.NumSrcRegs; i++) {
- if (fi->Src[i].Register.Indirect ||
- fi->Src[i].Register.Dimension ||
- fi->Src[i].Register.Absolute) {
- fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- }
- for (i = 0; i < fi->Instruction.NumDstRegs; i++) {
- if (fi->Dst[i].Register.Indirect || fi->Dst[i].Register.Dimension) {
- fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
- return -EINVAL;
- }
- }
- r = tgsi_opcode_to_c_opcode(fi->Instruction.Opcode, &opcode);
- if (r) {
- fprintf(stderr, "%s:%d unsupported\n", __func__, __LINE__);
- return r;
- }
- if (opcode == C_OPCODE_END) {
- return c_node_cfg_link(ts->node, &shader->end);
- }
- /* FIXME add flow instruction handling */
- memset(&instruction, 0, sizeof(struct c_instruction));
- instruction.nop = 0;
- for (j = 0; j < 4; j++) {
- instruction.op[instruction.nop].opcode = opcode;
- instruction.op[instruction.nop].ninput = fi->Instruction.NumSrcRegs;
- for (i = 0; i < fi->Instruction.NumSrcRegs; i++) {
- instruction.op[instruction.nop].input[i].vector = ts->v[fi->Src[i].Register.File][fi->Src[i].Register.Index];
- switch (j) {
- case 0:
- instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleX;
- break;
- case 1:
- instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleY;
- break;
- case 2:
- instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleZ;
- break;
- case 3:
- instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleW;
- break;
- default:
- return -EINVAL;
- }
- }
- instruction.op[instruction.nop].output.vector = ts->v[fi->Dst[0].Register.File][fi->Dst[0].Register.Index];
- switch (j) {
- case 0:
- instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_X : C_SWIZZLE_D;
- break;
- case 1:
- instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_Y : C_SWIZZLE_D;
- break;
- case 2:
- instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_Z : C_SWIZZLE_D;
- break;
- case 3:
- instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_W : C_SWIZZLE_D;
- break;
- default:
- return -EINVAL;
- }
- instruction.nop++;
- }
- return c_node_add_new_instruction(ts->node, &instruction);
-}
-
-int c_shader_from_tgsi(struct c_shader *shader, unsigned type,
- const struct tgsi_token *tokens)
-{
- struct tgsi_shader ts;
- int r = 0;
-
- c_shader_init(shader, type);
- r = tgsi_shader_init(&ts, tokens, shader);
- if (r)
- goto out_err;
- ts.shader = shader;
- ts.node = &shader->entry;
- while (!tgsi_parse_end_of_tokens(&ts.parser)) {
- tgsi_parse_token(&ts.parser);
- switch (ts.parser.FullToken.Token.Type) {
- case TGSI_TOKEN_TYPE_IMMEDIATE:
- r = ntransform_immediate(&ts);
- if (r)
- goto out_err;
- break;
- case TGSI_TOKEN_TYPE_DECLARATION:
- r = ntransform_declaration(&ts);
- if (r)
- goto out_err;
- break;
- case TGSI_TOKEN_TYPE_INSTRUCTION:
- r = ntransform_instruction(&ts);
- if (r)
- goto out_err;
- break;
- default:
- r = -EINVAL;
- goto out_err;
- }
- }
- tgsi_shader_destroy(&ts);
- return 0;
-out_err:
- c_shader_destroy(shader);
- tgsi_shader_destroy(&ts);
- return r;
-}
-
-static unsigned tgsi_file_to_c_file(unsigned file)
-{
- switch (file) {
- case TGSI_FILE_CONSTANT:
- return C_FILE_CONSTANT;
- case TGSI_FILE_INPUT:
- return C_FILE_INPUT;
- case TGSI_FILE_OUTPUT:
- return C_FILE_OUTPUT;
- case TGSI_FILE_TEMPORARY:
- return C_FILE_TEMPORARY;
- case TGSI_FILE_SAMPLER:
- return C_FILE_SAMPLER;
- case TGSI_FILE_ADDRESS:
- return C_FILE_ADDRESS;
- case TGSI_FILE_IMMEDIATE:
- return C_FILE_IMMEDIATE;
- case TGSI_FILE_PREDICATE:
- return C_FILE_PREDICATE;
- case TGSI_FILE_SYSTEM_VALUE:
- return C_FILE_SYSTEM_VALUE;
- case TGSI_FILE_NULL:
- return C_FILE_NULL;
- default:
- fprintf(stderr, "%s:%d unsupported file %d\n", __func__, __LINE__, file);
- return C_FILE_NULL;
- }
-}
-
-static unsigned tgsi_sname_to_c_sname(unsigned sname)
-{
- switch (sname) {
- case TGSI_SEMANTIC_POSITION:
- return C_SEMANTIC_POSITION;
- case TGSI_SEMANTIC_COLOR:
- return C_SEMANTIC_COLOR;
- case TGSI_SEMANTIC_BCOLOR:
- return C_SEMANTIC_BCOLOR;
- case TGSI_SEMANTIC_FOG:
- return C_SEMANTIC_FOG;
- case TGSI_SEMANTIC_PSIZE:
- return C_SEMANTIC_PSIZE;
- case TGSI_SEMANTIC_GENERIC:
- return C_SEMANTIC_GENERIC;
- case TGSI_SEMANTIC_NORMAL:
- return C_SEMANTIC_NORMAL;
- case TGSI_SEMANTIC_FACE:
- return C_SEMANTIC_FACE;
- case TGSI_SEMANTIC_EDGEFLAG:
- return C_SEMANTIC_EDGEFLAG;
- case TGSI_SEMANTIC_PRIMID:
- return C_SEMANTIC_PRIMID;
- case TGSI_SEMANTIC_INSTANCEID:
- return C_SEMANTIC_INSTANCEID;
- default:
- return C_SEMANTIC_GENERIC;
- }
-}
-
-static int tgsi_opcode_to_c_opcode(unsigned opcode, unsigned *copcode)
-{
- switch (opcode) {
- case TGSI_OPCODE_MOV:
- *copcode = C_OPCODE_MOV;
- return 0;
- case TGSI_OPCODE_MUL:
- *copcode = C_OPCODE_MUL;
- return 0;
- case TGSI_OPCODE_MAD:
- *copcode = C_OPCODE_MAD;
- return 0;
- case TGSI_OPCODE_END:
- *copcode = C_OPCODE_END;
- return 0;
- case TGSI_OPCODE_ARL:
- *copcode = C_OPCODE_ARL;
- return 0;
- case TGSI_OPCODE_LIT:
- *copcode = C_OPCODE_LIT;
- return 0;
- case TGSI_OPCODE_RCP:
- *copcode = C_OPCODE_RCP;
- return 0;
- case TGSI_OPCODE_RSQ:
- *copcode = C_OPCODE_RSQ;
- return 0;
- case TGSI_OPCODE_EXP:
- *copcode = C_OPCODE_EXP;
- return 0;
- case TGSI_OPCODE_LOG:
- *copcode = C_OPCODE_LOG;
- return 0;
- case TGSI_OPCODE_ADD:
- *copcode = C_OPCODE_ADD;
- return 0;
- case TGSI_OPCODE_DP3:
- *copcode = C_OPCODE_DP3;
- return 0;
- case TGSI_OPCODE_DP4:
- *copcode = C_OPCODE_DP4;
- return 0;
- case TGSI_OPCODE_DST:
- *copcode = C_OPCODE_DST;
- return 0;
- case TGSI_OPCODE_MIN:
- *copcode = C_OPCODE_MIN;
- return 0;
- case TGSI_OPCODE_MAX:
- *copcode = C_OPCODE_MAX;
- return 0;
- case TGSI_OPCODE_SLT:
- *copcode = C_OPCODE_SLT;
- return 0;
- case TGSI_OPCODE_SGE:
- *copcode = C_OPCODE_SGE;
- return 0;
- case TGSI_OPCODE_SUB:
- *copcode = C_OPCODE_SUB;
- return 0;
- case TGSI_OPCODE_LRP:
- *copcode = C_OPCODE_LRP;
- return 0;
- case TGSI_OPCODE_CND:
- *copcode = C_OPCODE_CND;
- return 0;
- case TGSI_OPCODE_DP2A:
- *copcode = C_OPCODE_DP2A;
- return 0;
- case TGSI_OPCODE_FRC:
- *copcode = C_OPCODE_FRC;
- return 0;
- case TGSI_OPCODE_CLAMP:
- *copcode = C_OPCODE_CLAMP;
- return 0;
- case TGSI_OPCODE_FLR:
- *copcode = C_OPCODE_FLR;
- return 0;
- case TGSI_OPCODE_ROUND:
- *copcode = C_OPCODE_ROUND;
- return 0;
- case TGSI_OPCODE_EX2:
- *copcode = C_OPCODE_EX2;
- return 0;
- case TGSI_OPCODE_LG2:
- *copcode = C_OPCODE_LG2;
- return 0;
- case TGSI_OPCODE_POW:
- *copcode = C_OPCODE_POW;
- return 0;
- case TGSI_OPCODE_XPD:
- *copcode = C_OPCODE_XPD;
- return 0;
- case TGSI_OPCODE_ABS:
- *copcode = C_OPCODE_ABS;
- return 0;
- case TGSI_OPCODE_RCC:
- *copcode = C_OPCODE_RCC;
- return 0;
- case TGSI_OPCODE_DPH:
- *copcode = C_OPCODE_DPH;
- return 0;
- case TGSI_OPCODE_COS:
- *copcode = C_OPCODE_COS;
- return 0;
- case TGSI_OPCODE_DDX:
- *copcode = C_OPCODE_DDX;
- return 0;
- case TGSI_OPCODE_DDY:
- *copcode = C_OPCODE_DDY;
- return 0;
- case TGSI_OPCODE_KILP:
- *copcode = C_OPCODE_KILP;
- return 0;
- case TGSI_OPCODE_PK2H:
- *copcode = C_OPCODE_PK2H;
- return 0;
- case TGSI_OPCODE_PK2US:
- *copcode = C_OPCODE_PK2US;
- return 0;
- case TGSI_OPCODE_PK4B:
- *copcode = C_OPCODE_PK4B;
- return 0;
- case TGSI_OPCODE_PK4UB:
- *copcode = C_OPCODE_PK4UB;
- return 0;
- case TGSI_OPCODE_RFL:
- *copcode = C_OPCODE_RFL;
- return 0;
- case TGSI_OPCODE_SEQ:
- *copcode = C_OPCODE_SEQ;
- return 0;
- case TGSI_OPCODE_SFL:
- *copcode = C_OPCODE_SFL;
- return 0;
- case TGSI_OPCODE_SGT:
- *copcode = C_OPCODE_SGT;
- return 0;
- case TGSI_OPCODE_SIN:
- *copcode = C_OPCODE_SIN;
- return 0;
- case TGSI_OPCODE_SLE:
- *copcode = C_OPCODE_SLE;
- return 0;
- case TGSI_OPCODE_SNE:
- *copcode = C_OPCODE_SNE;
- return 0;
- case TGSI_OPCODE_STR:
- *copcode = C_OPCODE_STR;
- return 0;
- case TGSI_OPCODE_TEX:
- *copcode = C_OPCODE_TEX;
- return 0;
- case TGSI_OPCODE_TXD:
- *copcode = C_OPCODE_TXD;
- return 0;
- case TGSI_OPCODE_TXP:
- *copcode = C_OPCODE_TXP;
- return 0;
- case TGSI_OPCODE_UP2H:
- *copcode = C_OPCODE_UP2H;
- return 0;
- case TGSI_OPCODE_UP2US:
- *copcode = C_OPCODE_UP2US;
- return 0;
- case TGSI_OPCODE_UP4B:
- *copcode = C_OPCODE_UP4B;
- return 0;
- case TGSI_OPCODE_UP4UB:
- *copcode = C_OPCODE_UP4UB;
- return 0;
- case TGSI_OPCODE_X2D:
- *copcode = C_OPCODE_X2D;
- return 0;
- case TGSI_OPCODE_ARA:
- *copcode = C_OPCODE_ARA;
- return 0;
- case TGSI_OPCODE_ARR:
- *copcode = C_OPCODE_ARR;
- return 0;
- case TGSI_OPCODE_BRA:
- *copcode = C_OPCODE_BRA;
- return 0;
- case TGSI_OPCODE_CAL:
- *copcode = C_OPCODE_CAL;
- return 0;
- case TGSI_OPCODE_RET:
- *copcode = C_OPCODE_RET;
- return 0;
- case TGSI_OPCODE_SSG:
- *copcode = C_OPCODE_SSG;
- return 0;
- case TGSI_OPCODE_CMP:
- *copcode = C_OPCODE_CMP;
- return 0;
- case TGSI_OPCODE_SCS:
- *copcode = C_OPCODE_SCS;
- return 0;
- case TGSI_OPCODE_TXB:
- *copcode = C_OPCODE_TXB;
- return 0;
- case TGSI_OPCODE_NRM:
- *copcode = C_OPCODE_NRM;
- return 0;
- case TGSI_OPCODE_DIV:
- *copcode = C_OPCODE_DIV;
- return 0;
- case TGSI_OPCODE_DP2:
- *copcode = C_OPCODE_DP2;
- return 0;
- case TGSI_OPCODE_TXL:
- *copcode = C_OPCODE_TXL;
- return 0;
- case TGSI_OPCODE_BRK:
- *copcode = C_OPCODE_BRK;
- return 0;
- case TGSI_OPCODE_IF:
- *copcode = C_OPCODE_IF;
- return 0;
- case TGSI_OPCODE_ELSE:
- *copcode = C_OPCODE_ELSE;
- return 0;
- case TGSI_OPCODE_ENDIF:
- *copcode = C_OPCODE_ENDIF;
- return 0;
- case TGSI_OPCODE_PUSHA:
- *copcode = C_OPCODE_PUSHA;
- return 0;
- case TGSI_OPCODE_POPA:
- *copcode = C_OPCODE_POPA;
- return 0;
- case TGSI_OPCODE_CEIL:
- *copcode = C_OPCODE_CEIL;
- return 0;
- case TGSI_OPCODE_I2F:
- *copcode = C_OPCODE_I2F;
- return 0;
- case TGSI_OPCODE_NOT:
- *copcode = C_OPCODE_NOT;
- return 0;
- case TGSI_OPCODE_TRUNC:
- *copcode = C_OPCODE_TRUNC;
- return 0;
- case TGSI_OPCODE_SHL:
- *copcode = C_OPCODE_SHL;
- return 0;
- case TGSI_OPCODE_AND:
- *copcode = C_OPCODE_AND;
- return 0;
- case TGSI_OPCODE_OR:
- *copcode = C_OPCODE_OR;
- return 0;
- case TGSI_OPCODE_MOD:
- *copcode = C_OPCODE_MOD;
- return 0;
- case TGSI_OPCODE_XOR:
- *copcode = C_OPCODE_XOR;
- return 0;
- case TGSI_OPCODE_SAD:
- *copcode = C_OPCODE_SAD;
- return 0;
- case TGSI_OPCODE_TXF:
- *copcode = C_OPCODE_TXF;
- return 0;
- case TGSI_OPCODE_TXQ:
- *copcode = C_OPCODE_TXQ;
- return 0;
- case TGSI_OPCODE_CONT:
- *copcode = C_OPCODE_CONT;
- return 0;
- case TGSI_OPCODE_EMIT:
- *copcode = C_OPCODE_EMIT;
- return 0;
- case TGSI_OPCODE_ENDPRIM:
- *copcode = C_OPCODE_ENDPRIM;
- return 0;
- case TGSI_OPCODE_BGNLOOP:
- *copcode = C_OPCODE_BGNLOOP;
- return 0;
- case TGSI_OPCODE_BGNSUB:
- *copcode = C_OPCODE_BGNSUB;
- return 0;
- case TGSI_OPCODE_ENDLOOP:
- *copcode = C_OPCODE_ENDLOOP;
- return 0;
- case TGSI_OPCODE_ENDSUB:
- *copcode = C_OPCODE_ENDSUB;
- return 0;
- case TGSI_OPCODE_NOP:
- *copcode = C_OPCODE_NOP;
- return 0;
- case TGSI_OPCODE_NRM4:
- *copcode = C_OPCODE_NRM4;
- return 0;
- case TGSI_OPCODE_CALLNZ:
- *copcode = C_OPCODE_CALLNZ;
- return 0;
- case TGSI_OPCODE_IFC:
- *copcode = C_OPCODE_IFC;
- return 0;
- case TGSI_OPCODE_BREAKC:
- *copcode = C_OPCODE_BREAKC;
- return 0;
- case TGSI_OPCODE_KIL:
- *copcode = C_OPCODE_KIL;
- return 0;
- case TGSI_OPCODE_F2I:
- *copcode = C_OPCODE_F2I;
- return 0;
- case TGSI_OPCODE_IDIV:
- *copcode = C_OPCODE_IDIV;
- return 0;
- case TGSI_OPCODE_IMAX:
- *copcode = C_OPCODE_IMAX;
- return 0;
- case TGSI_OPCODE_IMIN:
- *copcode = C_OPCODE_IMIN;
- return 0;
- case TGSI_OPCODE_INEG:
- *copcode = C_OPCODE_INEG;
- return 0;
- case TGSI_OPCODE_ISGE:
- *copcode = C_OPCODE_ISGE;
- return 0;
- case TGSI_OPCODE_ISHR:
- *copcode = C_OPCODE_ISHR;
- return 0;
- case TGSI_OPCODE_ISLT:
- *copcode = C_OPCODE_ISLT;
- return 0;
- case TGSI_OPCODE_F2U:
- *copcode = C_OPCODE_F2U;
- return 0;
- case TGSI_OPCODE_U2F:
- *copcode = C_OPCODE_U2F;
- return 0;
- case TGSI_OPCODE_UADD:
- *copcode = C_OPCODE_UADD;
- return 0;
- case TGSI_OPCODE_UDIV:
- *copcode = C_OPCODE_UDIV;
- return 0;
- case TGSI_OPCODE_UMAD:
- *copcode = C_OPCODE_UMAD;
- return 0;
- case TGSI_OPCODE_UMAX:
- *copcode = C_OPCODE_UMAX;
- return 0;
- case TGSI_OPCODE_UMIN:
- *copcode = C_OPCODE_UMIN;
- return 0;
- case TGSI_OPCODE_UMOD:
- *copcode = C_OPCODE_UMOD;
- return 0;
- case TGSI_OPCODE_UMUL:
- *copcode = C_OPCODE_UMUL;
- return 0;
- case TGSI_OPCODE_USEQ:
- *copcode = C_OPCODE_USEQ;
- return 0;
- case TGSI_OPCODE_USGE:
- *copcode = C_OPCODE_USGE;
- return 0;
- case TGSI_OPCODE_USHR:
- *copcode = C_OPCODE_USHR;
- return 0;
- case TGSI_OPCODE_USLT:
- *copcode = C_OPCODE_USLT;
- return 0;
- case TGSI_OPCODE_USNE:
- *copcode = C_OPCODE_USNE;
- return 0;
- case TGSI_OPCODE_SWITCH:
- *copcode = C_OPCODE_SWITCH;
- return 0;
- case TGSI_OPCODE_CASE:
- *copcode = C_OPCODE_CASE;
- return 0;
- case TGSI_OPCODE_DEFAULT:
- *copcode = C_OPCODE_DEFAULT;
- return 0;
- case TGSI_OPCODE_ENDSWITCH:
- *copcode = C_OPCODE_ENDSWITCH;
- return 0;
- default:
- fprintf(stderr, "%s:%d unsupported opcode %d\n", __func__, __LINE__, opcode);
- return -EINVAL;
- }
-}
diff --git a/src/gallium/drivers/r600/r600_context.c b/src/gallium/drivers/r600/r600_context.c
index 05575b5767..edde80c660 100644
--- a/src/gallium/drivers/r600/r600_context.c
+++ b/src/gallium/drivers/r600/r600_context.c
@@ -29,9 +29,9 @@
#include <util/u_format.h>
#include <util/u_memory.h>
#include <util/u_blitter.h>
-#include "r600_resource.h"
#include "r600_screen.h"
#include "r600_context.h"
+#include "r600_resource.h"
#include "r600d.h"
static void r600_destroy_context(struct pipe_context *context)
@@ -41,26 +41,31 @@ static void r600_destroy_context(struct pipe_context *context)
FREE(rctx);
}
-static void r600_flush(struct pipe_context *ctx, unsigned flags,
+void r600_flush(struct pipe_context *ctx, unsigned flags,
struct pipe_fence_handle **fence)
{
struct r600_context *rctx = r600_context(ctx);
struct r600_screen *rscreen = rctx->screen;
static int dc = 0;
+ char dname[256];
if (radeon_ctx_pm4(rctx->ctx))
return;
/* FIXME dumping should be removed once shader support instructions
* without throwing bad code
*/
- if (!dc)
- radeon_ctx_dump_bof(rctx->ctx, "gallium.bof");
-#if 0
+ if (!rctx->ctx->cpm4)
+ goto out;
+ sprintf(dname, "gallium-%08d.bof", dc);
+ if (dc < 1)
+ radeon_ctx_dump_bof(rctx->ctx, dname);
+#if 1
radeon_ctx_submit(rctx->ctx);
#endif
+ dc++;
+out:
rctx->ctx = radeon_ctx_decref(rctx->ctx);
rctx->ctx = radeon_ctx(rscreen->rw);
- dc++;
}
static void r600_init_config(struct r600_context *rctx)
@@ -202,27 +207,9 @@ static void r600_init_config(struct r600_context *rctx)
num_es_stack_entries = 0;
break;
}
- printf("ps_prio : %d\n", ps_prio);
- printf("vs_prio : %d\n", vs_prio);
- printf("gs_prio : %d\n", gs_prio);
- printf("es_prio : %d\n", es_prio);
- printf("num_ps_gprs : %d\n", num_ps_gprs);
- printf("num_vs_gprs : %d\n", num_vs_gprs);
- printf("num_gs_gprs : %d\n", num_gs_gprs);
- printf("num_es_gprs : %d\n", num_es_gprs);
- printf("num_temp_gprs : %d\n", num_temp_gprs);
- printf("num_ps_threads : %d\n", num_ps_threads);
- printf("num_vs_threads : %d\n", num_vs_threads);
- printf("num_gs_threads : %d\n", num_gs_threads);
- printf("num_es_threads : %d\n", num_es_threads);
- printf("num_ps_stack_entries : %d\n", num_ps_stack_entries);
- printf("num_vs_stack_entries : %d\n", num_vs_stack_entries);
- printf("num_gs_stack_entries : %d\n", num_gs_stack_entries);
- printf("num_es_stack_entries : %d\n", num_es_stack_entries);
-
- rctx->config = radeon_state(rctx->rw, R600_CONFIG_TYPE, R600_CONFIG);
+ rctx->hw_states.config = radeon_state(rctx->rw, R600_CONFIG_TYPE, R600_CONFIG);
- rctx->config->states[R600_CONFIG__SQ_CONFIG] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_CONFIG] = 0x00000000;
switch (family) {
case CHIP_RV610:
case CHIP_RV620:
@@ -231,75 +218,75 @@ static void r600_init_config(struct r600_context *rctx)
case CHIP_RV710:
break;
default:
- rctx->config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_VC_ENABLE(1);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_VC_ENABLE(1);
break;
}
- rctx->config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_DX9_CONSTS(1);
- rctx->config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_ALU_INST_PREFER_VECTOR(1);
- rctx->config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_PS_PRIO(ps_prio);
- rctx->config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_VS_PRIO(vs_prio);
- rctx->config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_GS_PRIO(gs_prio);
- rctx->config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_ES_PRIO(es_prio);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_DX9_CONSTS(1);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_ALU_INST_PREFER_VECTOR(1);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_PS_PRIO(ps_prio);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_VS_PRIO(vs_prio);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_GS_PRIO(gs_prio);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_ES_PRIO(es_prio);
- rctx->config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_1] = 0;
- rctx->config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_1] |= S_008C04_NUM_PS_GPRS(num_ps_gprs);
- rctx->config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_1] |= S_008C04_NUM_VS_GPRS(num_vs_gprs);
- rctx->config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_1] |= S_008C04_NUM_CLAUSE_TEMP_GPRS(num_temp_gprs);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_1] = 0;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_1] |= S_008C04_NUM_PS_GPRS(num_ps_gprs);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_1] |= S_008C04_NUM_VS_GPRS(num_vs_gprs);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_1] |= S_008C04_NUM_CLAUSE_TEMP_GPRS(num_temp_gprs);
- rctx->config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_2] = 0;
- rctx->config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_2] |= S_008C08_NUM_GS_GPRS(num_gs_gprs);
- rctx->config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_2] |= S_008C08_NUM_GS_GPRS(num_es_gprs);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_2] = 0;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_2] |= S_008C08_NUM_GS_GPRS(num_gs_gprs);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_2] |= S_008C08_NUM_GS_GPRS(num_es_gprs);
- rctx->config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] = 0;
- rctx->config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] |= S_008C0C_NUM_PS_THREADS(num_ps_threads);
- rctx->config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] |= S_008C0C_NUM_VS_THREADS(num_vs_threads);
- rctx->config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] |= S_008C0C_NUM_GS_THREADS(num_gs_threads);
- rctx->config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] |= S_008C0C_NUM_ES_THREADS(num_es_threads);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] = 0;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] |= S_008C0C_NUM_PS_THREADS(num_ps_threads);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] |= S_008C0C_NUM_VS_THREADS(num_vs_threads);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] |= S_008C0C_NUM_GS_THREADS(num_gs_threads);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] |= S_008C0C_NUM_ES_THREADS(num_es_threads);
- rctx->config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_1] = 0;
- rctx->config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_1] |= S_008C10_NUM_PS_STACK_ENTRIES(num_ps_stack_entries);
- rctx->config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_1] |= S_008C10_NUM_VS_STACK_ENTRIES(num_vs_stack_entries);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_1] = 0;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_1] |= S_008C10_NUM_PS_STACK_ENTRIES(num_ps_stack_entries);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_1] |= S_008C10_NUM_VS_STACK_ENTRIES(num_vs_stack_entries);
- rctx->config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_2] = 0;
- rctx->config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_2] |= S_008C14_NUM_GS_STACK_ENTRIES(num_gs_stack_entries);
- rctx->config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_2] |= S_008C14_NUM_ES_STACK_ENTRIES(num_es_stack_entries);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_2] = 0;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_2] |= S_008C14_NUM_GS_STACK_ENTRIES(num_gs_stack_entries);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_2] |= S_008C14_NUM_ES_STACK_ENTRIES(num_es_stack_entries);
- rctx->config->states[R600_CONFIG__SQ_DYN_GPR_CNTL_PS_FLUSH_REQ] = 0x00004000;
- rctx->config->states[R600_CONFIG__TA_CNTL_AUX] = 0x07000002;
- rctx->config->states[R600_CONFIG__VC_ENHANCE] = 0x00000000;
- rctx->config->states[R600_CONFIG__DB_DEBUG] = 0x00000000;
- rctx->config->states[R600_CONFIG__DB_WATERMARKS] = 0x00420204;
- rctx->config->states[R600_CONFIG__SX_MISC] = 0x00000000;
- rctx->config->states[R600_CONFIG__SPI_THREAD_GROUPING] = 0x00000001;
- rctx->config->states[R600_CONFIG__CB_SHADER_CONTROL] = 0x00000003;
- rctx->config->states[R600_CONFIG__SQ_ESGS_RING_ITEMSIZE] = 0x00000000;
- rctx->config->states[R600_CONFIG__SQ_GSVS_RING_ITEMSIZE] = 0x00000000;
- rctx->config->states[R600_CONFIG__SQ_ESTMP_RING_ITEMSIZE] = 0x00000000;
- rctx->config->states[R600_CONFIG__SQ_GSTMP_RING_ITEMSIZE] = 0x00000000;
- rctx->config->states[R600_CONFIG__SQ_VSTMP_RING_ITEMSIZE] = 0x00000000;
- rctx->config->states[R600_CONFIG__SQ_PSTMP_RING_ITEMSIZE] = 0x00000000;
- rctx->config->states[R600_CONFIG__SQ_FBUF_RING_ITEMSIZE] = 0x00000000;
- rctx->config->states[R600_CONFIG__SQ_REDUC_RING_ITEMSIZE] = 0x00000000;
- rctx->config->states[R600_CONFIG__SQ_GS_VERT_ITEMSIZE] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_OUTPUT_PATH_CNTL] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_HOS_CNTL] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_HOS_MAX_TESS_LEVEL] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_HOS_MIN_TESS_LEVEL] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_HOS_REUSE_DEPTH] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_GROUP_PRIM_TYPE] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_GROUP_FIRST_DECR] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_GROUP_DECR] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_GROUP_VECT_0_CNTL] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_GROUP_VECT_1_CNTL] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_GROUP_VECT_0_FMT_CNTL] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_GROUP_VECT_1_FMT_CNTL] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_GS_MODE] = 0x00000000;
- rctx->config->states[R600_CONFIG__PA_SC_MODE_CNTL] = 0x00514000;
- rctx->config->states[R600_CONFIG__VGT_STRMOUT_EN] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_REUSE_OFF] = 0x00000001;
- rctx->config->states[R600_CONFIG__VGT_VTX_CNT_EN] = 0x00000000;
- rctx->config->states[R600_CONFIG__VGT_STRMOUT_BUFFER_EN] = 0x00000000;
- radeon_state_pm4(rctx->config);
+ rctx->hw_states.config->states[R600_CONFIG__SQ_DYN_GPR_CNTL_PS_FLUSH_REQ] = 0x00004000;
+ rctx->hw_states.config->states[R600_CONFIG__TA_CNTL_AUX] = 0x07000002;
+ rctx->hw_states.config->states[R600_CONFIG__VC_ENHANCE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__DB_DEBUG] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__DB_WATERMARKS] = 0x00420204;
+ rctx->hw_states.config->states[R600_CONFIG__SX_MISC] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__SPI_THREAD_GROUPING] = 0x00000001;
+ rctx->hw_states.config->states[R600_CONFIG__CB_SHADER_CONTROL] = 0x00000003;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_ESGS_RING_ITEMSIZE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_GSVS_RING_ITEMSIZE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_ESTMP_RING_ITEMSIZE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_GSTMP_RING_ITEMSIZE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_VSTMP_RING_ITEMSIZE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_PSTMP_RING_ITEMSIZE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_FBUF_RING_ITEMSIZE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_REDUC_RING_ITEMSIZE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__SQ_GS_VERT_ITEMSIZE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_OUTPUT_PATH_CNTL] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_HOS_CNTL] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_HOS_MAX_TESS_LEVEL] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_HOS_MIN_TESS_LEVEL] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_HOS_REUSE_DEPTH] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_GROUP_PRIM_TYPE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_GROUP_FIRST_DECR] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_GROUP_DECR] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_GROUP_VECT_0_CNTL] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_GROUP_VECT_1_CNTL] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_GROUP_VECT_0_FMT_CNTL] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_GROUP_VECT_1_FMT_CNTL] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_GS_MODE] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__PA_SC_MODE_CNTL] = 0x00514000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_STRMOUT_EN] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_REUSE_OFF] = 0x00000001;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_VTX_CNT_EN] = 0x00000000;
+ rctx->hw_states.config->states[R600_CONFIG__VGT_STRMOUT_BUFFER_EN] = 0x00000000;
+ radeon_state_pm4(rctx->hw_states.config);
}
struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv)
@@ -313,9 +300,7 @@ struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv)
rctx->context.screen = screen;
rctx->context.priv = priv;
rctx->context.destroy = r600_destroy_context;
- rctx->context.draw_arrays = r600_draw_arrays;
- rctx->context.draw_elements = r600_draw_elements;
- rctx->context.draw_range_elements = r600_draw_range_elements;
+ rctx->context.draw_vbo = r600_draw_vbo;
rctx->context.flush = r600_flush;
/* Easy accessing of screen/winsys. */
@@ -333,20 +318,6 @@ struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv)
return NULL;
}
- rctx->cb_cntl = radeon_state(rscreen->rw, R600_CB_CNTL_TYPE, R600_CB_CNTL);
- rctx->cb_cntl->states[R600_CB_CNTL__CB_SHADER_MASK] = 0x0000000F;
- rctx->cb_cntl->states[R600_CB_CNTL__CB_TARGET_MASK] = 0x0000000F;
- rctx->cb_cntl->states[R600_CB_CNTL__CB_COLOR_CONTROL] = 0x00CC0000;
- rctx->cb_cntl->states[R600_CB_CNTL__PA_SC_AA_CONFIG] = 0x00000000;
- rctx->cb_cntl->states[R600_CB_CNTL__PA_SC_AA_SAMPLE_LOCS_MCTX] = 0x00000000;
- rctx->cb_cntl->states[R600_CB_CNTL__PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX] = 0x00000000;
- rctx->cb_cntl->states[R600_CB_CNTL__CB_CLRCMP_CONTROL] = 0x01000000;
- rctx->cb_cntl->states[R600_CB_CNTL__CB_CLRCMP_SRC] = 0x00000000;
- rctx->cb_cntl->states[R600_CB_CNTL__CB_CLRCMP_DST] = 0x000000FF;
- rctx->cb_cntl->states[R600_CB_CNTL__CB_CLRCMP_MSK] = 0xFFFFFFFF;
- rctx->cb_cntl->states[R600_CB_CNTL__PA_SC_AA_MASK] = 0xFFFFFFFF;
- radeon_state_pm4(rctx->cb_cntl);
-
r600_init_config(rctx);
rctx->ctx = radeon_ctx(rscreen->rw);
diff --git a/src/gallium/drivers/r600/r600_context.h b/src/gallium/drivers/r600/r600_context.h
index f27ff58ed4..76d5de8653 100644
--- a/src/gallium/drivers/r600/r600_context.h
+++ b/src/gallium/drivers/r600/r600_context.h
@@ -23,6 +23,7 @@
#ifndef R600_CONTEXT_H
#define R600_CONTEXT_H
+#include <stdio.h>
#include <pipe/p_state.h>
#include <pipe/p_context.h>
#include <tgsi/tgsi_scan.h>
@@ -33,17 +34,74 @@
#include "r600_shader.h"
/* XXX move this to a more appropriate place */
-struct r600_vertex_elements_state
+union pipe_states {
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_poly_stipple poly_stipple;
+ struct pipe_scissor_state scissor;
+ struct pipe_clip_state clip;
+ struct pipe_shader_state shader;
+ struct pipe_depth_state depth;
+ struct pipe_stencil_state stencil;
+ struct pipe_alpha_state alpha;
+ struct pipe_depth_stencil_alpha_state dsa;
+ struct pipe_blend_state blend;
+ struct pipe_blend_color blend_color;
+ struct pipe_stencil_ref stencil_ref;
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_sampler_state sampler;
+ struct pipe_sampler_view sampler_view;
+ struct pipe_viewport_state viewport;
+};
+
+enum pipe_state_type {
+ pipe_rasterizer_type = 1,
+ pipe_poly_stipple_type,
+ pipe_scissor_type,
+ pipe_clip_type,
+ pipe_shader_type,
+ pipe_depth_type,
+ pipe_stencil_type,
+ pipe_alpha_type,
+ pipe_dsa_type,
+ pipe_blend_type,
+ pipe_stencil_ref_type,
+ pipe_framebuffer_type,
+ pipe_sampler_type,
+ pipe_sampler_view_type,
+ pipe_viewport_type,
+ pipe_type_count
+};
+
+struct r600_context_state {
+ union pipe_states state;
+ unsigned refcount;
+ unsigned type;
+ struct radeon_state *rstate;
+ struct r600_shader shader;
+ struct radeon_bo *bo;
+};
+
+struct r600_vertex_element
{
- unsigned count;
- struct pipe_vertex_element elements[32];
+ unsigned refcount;
+ unsigned count;
+ struct pipe_vertex_element elements[32];
};
-struct r600_pipe_shader {
- unsigned type;
- struct r600_shader shader;
- struct radeon_bo *bo;
- struct radeon_state *state;
+struct r600_context_hw_states {
+ struct radeon_state *rasterizer;
+ struct radeon_state *scissor;
+ struct radeon_state *dsa;
+ struct radeon_state *blend;
+ struct radeon_state *viewport;
+ struct radeon_state *cb[8];
+ struct radeon_state *config;
+ struct radeon_state *cb_cntl;
+ struct radeon_state *db;
+ unsigned ps_nresource;
+ unsigned ps_nsampler;
+ struct radeon_state *ps_resource[160];
+ struct radeon_state *ps_sampler[16];
};
struct r600_context {
@@ -51,20 +109,39 @@ struct r600_context {
struct r600_screen *screen;
struct radeon *rw;
struct radeon_ctx *ctx;
- struct radeon_state *cb_cntl;
- struct radeon_state *db;
- struct radeon_state *config;
- struct r600_pipe_shader *ps_shader;
- struct r600_pipe_shader *vs_shader;
+ struct blitter_context *blitter;
+ struct radeon_draw *draw;
+ /* hw states */
+ struct r600_context_hw_states hw_states;
+ /* pipe states */
unsigned flat_shade;
+ unsigned ps_nsampler;
+ unsigned vs_nsampler;
+ unsigned ps_nsampler_view;
+ unsigned vs_nsampler_view;
unsigned nvertex_buffer;
- struct r600_vertex_elements_state *vertex_elements;
+ struct r600_context_state *rasterizer;
+ struct r600_context_state *poly_stipple;
+ struct r600_context_state *scissor;
+ struct r600_context_state *clip;
+ struct r600_context_state *ps_shader;
+ struct r600_context_state *vs_shader;
+ struct r600_context_state *depth;
+ struct r600_context_state *stencil;
+ struct r600_context_state *alpha;
+ struct r600_context_state *dsa;
+ struct r600_context_state *blend;
+ struct r600_context_state *stencil_ref;
+ struct r600_context_state *viewport;
+ struct r600_context_state *framebuffer;
+ struct r600_context_state *ps_sampler[PIPE_MAX_ATTRIBS];
+ struct r600_context_state *vs_sampler[PIPE_MAX_ATTRIBS];
+ struct r600_context_state *ps_sampler_view[PIPE_MAX_ATTRIBS];
+ struct r600_context_state *vs_sampler_view[PIPE_MAX_ATTRIBS];
+ struct r600_vertex_element *vertex_elements;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
- struct blitter_context *blitter;
- struct pipe_stencil_ref stencil_ref;
- struct pipe_framebuffer_state fb_state;
- struct radeon_draw *draw;
- struct pipe_viewport_state viewport;
+ struct pipe_index_buffer index_buffer;
+ struct pipe_blend_color blend_color;
};
/* Convenience cast wrapper. */
@@ -73,27 +150,32 @@ static INLINE struct r600_context *r600_context(struct pipe_context *pipe)
return (struct r600_context*)pipe;
}
-void r600_draw_arrays(struct pipe_context *ctx, unsigned mode,
- unsigned start, unsigned count);
-void r600_draw_elements(struct pipe_context *ctx,
- struct pipe_resource *index_buffer,
- unsigned index_size, int index_bias, unsigned mode,
- unsigned start, unsigned count);
-void r600_draw_range_elements(struct pipe_context *ctx,
- struct pipe_resource *index_buffer,
- unsigned index_size, int index_bias, unsigned min_index,
- unsigned max_index, unsigned mode,
- unsigned start, unsigned count);
+struct r600_context_state *r600_context_state(struct r600_context *rctx, unsigned type, const void *state);
+struct r600_context_state *r600_context_state_incref(struct r600_context_state *rstate);
+struct r600_context_state *r600_context_state_decref(struct r600_context_state *rstate);
+void r600_flush(struct pipe_context *ctx, unsigned flags,
+ struct pipe_fence_handle **fence);
+
+int r600_context_hw_states(struct r600_context *rctx);
+
+void r600_draw_vbo(struct pipe_context *ctx,
+ const struct pipe_draw_info *info);
void r600_init_blit_functions(struct r600_context *rctx);
void r600_init_state_functions(struct r600_context *rctx);
void r600_init_query_functions(struct r600_context* rctx);
struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv);
-void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *rpshader);
-struct r600_pipe_shader *r600_pipe_shader_create(struct pipe_context *ctx,
- unsigned type,
- const struct tgsi_token *tokens);
-int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *rpshader);
+extern int r600_pipe_shader_create(struct pipe_context *ctx,
+ struct r600_context_state *rstate,
+ const struct tgsi_token *tokens);
+extern int r600_pipe_shader_update(struct pipe_context *ctx,
+ struct r600_context_state *rstate);
+
+#define R600_ERR(fmt, args...) \
+ fprintf(stderr, "EE %s/%s:%d - "fmt, __FILE__, __func__, __LINE__, ##args)
+uint32_t r600_translate_texformat(enum pipe_format format,
+ const unsigned char *swizzle_view,
+ uint32_t *word4_p, uint32_t *yuv_format_p);
#endif
diff --git a/src/gallium/drivers/r600/r600_draw.c b/src/gallium/drivers/r600/r600_draw.c
index 724fb6c988..f058455162 100644
--- a/src/gallium/drivers/r600/r600_draw.c
+++ b/src/gallium/drivers/r600/r600_draw.c
@@ -33,7 +33,8 @@
#include <util/u_memory.h>
#include "r600_screen.h"
#include "r600_context.h"
-#include "r600d.h"
+#include "r600_resource.h"
+#include "r600_state_inlines.h"
struct r600_draw {
struct pipe_context *ctx;
@@ -51,11 +52,15 @@ static int r600_draw_common(struct r600_draw *draw)
struct r600_context *rctx = r600_context(draw->ctx);
struct r600_screen *rscreen = rctx->screen;
struct radeon_state *vs_resource;
- struct r600_buffer *rbuffer;
+ struct r600_resource *rbuffer;
unsigned i, j, offset, format, prim;
u32 vgt_dma_index_type, vgt_draw_initiator;
+ struct pipe_vertex_buffer *vertex_buffer;
int r;
+ r = r600_context_hw_states(rctx);
+ if (r)
+ return r;
switch (draw->index_size) {
case 2:
vgt_draw_initiator = 0;
@@ -83,29 +88,19 @@ static int r600_draw_common(struct r600_draw *draw)
r = r600_pipe_shader_update(draw->ctx, rctx->ps_shader);
if (r)
return r;
- r = radeon_draw_set(rctx->draw, rctx->vs_shader->state);
- if (r)
- return r;
- r = radeon_draw_set(rctx->draw, rctx->ps_shader->state);
+ r = radeon_draw_set(rctx->draw, rctx->vs_shader->rstate);
if (r)
return r;
- r = radeon_draw_set(rctx->draw, rctx->cb_cntl);
- if (r)
- return r;
- r = radeon_draw_set(rctx->draw, rctx->db);
- if (r)
- return r;
- r = radeon_draw_set(rctx->draw, rctx->config);
+ r = radeon_draw_set(rctx->draw, rctx->ps_shader->rstate);
if (r)
return r;
for (i = 0 ; i < rctx->vertex_elements->count; i++) {
j = rctx->vertex_elements->elements[i].vertex_buffer_index;
- rbuffer = (struct r600_buffer*)rctx->vertex_buffer[j].buffer;
- offset = rctx->vertex_elements->elements[i].src_offset + rctx->vertex_buffer[j].buffer_offset;
- r = r600_conv_pipe_format(rctx->vertex_elements->elements[i].src_format, &format);
- if (r)
- return r;
+ vertex_buffer = &rctx->vertex_buffer[j];
+ rbuffer = (struct r600_resource*)vertex_buffer->buffer;
+ offset = rctx->vertex_elements->elements[i].src_offset + vertex_buffer->buffer_offset;
+ format = r600_translate_colorformat(rctx->vertex_elements->elements[i].src_format);
vs_resource = radeon_state(rscreen->rw, R600_VS_RESOURCE_TYPE, R600_VS_RESOURCE + i);
if (vs_resource == NULL)
return -ENOMEM;
@@ -113,7 +108,7 @@ static int r600_draw_common(struct r600_draw *draw)
vs_resource->nbo = 1;
vs_resource->states[R600_PS_RESOURCE__RESOURCE0_WORD0] = offset;
vs_resource->states[R600_PS_RESOURCE__RESOURCE0_WORD1] = rbuffer->bo->size - offset;
- vs_resource->states[R600_PS_RESOURCE__RESOURCE0_WORD2] = S_038008_STRIDE(rctx->vertex_buffer[j].stride) |
+ vs_resource->states[R600_PS_RESOURCE__RESOURCE0_WORD2] = S_038008_STRIDE(vertex_buffer->stride) |
S_038008_DATA_FORMAT(format);
vs_resource->states[R600_PS_RESOURCE__RESOURCE0_WORD3] = 0x00000000;
vs_resource->states[R600_PS_RESOURCE__RESOURCE0_WORD4] = 0x00000000;
@@ -132,7 +127,7 @@ static int r600_draw_common(struct r600_draw *draw)
draw->draw->states[R600_DRAW__VGT_NUM_INDICES] = draw->count;
draw->draw->states[R600_DRAW__VGT_DRAW_INITIATOR] = vgt_draw_initiator;
if (draw->index_buffer) {
- rbuffer = (struct r600_buffer*)draw->index_buffer;
+ rbuffer = (struct r600_resource*)draw->index_buffer;
draw->draw->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
draw->draw->placement[0] = RADEON_GEM_DOMAIN_GTT;
draw->draw->placement[1] = RADEON_GEM_DOMAIN_GTT;
@@ -160,58 +155,39 @@ static int r600_draw_common(struct r600_draw *draw)
return r;
/* FIXME */
r = radeon_ctx_set_draw_new(rctx->ctx, rctx->draw);
+ if (r == -EBUSY) {
+ r600_flush(draw->ctx, 0, NULL);
+ r = radeon_ctx_set_draw_new(rctx->ctx, rctx->draw);
+ }
if (r)
return r;
rctx->draw = radeon_draw_duplicate(rctx->draw);
return 0;
}
-void r600_draw_range_elements(struct pipe_context *ctx,
- struct pipe_resource *index_buffer,
- unsigned index_size, int index_bias, unsigned min_index,
- unsigned max_index, unsigned mode,
- unsigned start, unsigned count)
+void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
{
+ struct r600_context *rctx = r600_context(ctx);
struct r600_draw draw;
- assert(index_bias == 0);
- draw.ctx = ctx;
- draw.mode = mode;
- draw.start = start;
- draw.count = count;
- draw.index_size = index_size;
- draw.index_buffer = index_buffer;
-printf("index_size %d min %d max %d start %d count %d\n", index_size, min_index, max_index, start, count);
- r600_draw_common(&draw);
-}
-
-void r600_draw_elements(struct pipe_context *ctx,
- struct pipe_resource *index_buffer,
- unsigned index_size, int index_bias, unsigned mode,
- unsigned start, unsigned count)
-{
- struct r600_draw draw;
- assert(index_bias == 0);
+ assert(info->index_bias == 0);
draw.ctx = ctx;
- draw.mode = mode;
- draw.start = start;
- draw.count = count;
- draw.index_size = index_size;
- draw.index_buffer = index_buffer;
- r600_draw_common(&draw);
-}
+ draw.mode = info->mode;
+ draw.start = info->start;
+ draw.count = info->count;
+ if (info->indexed && rctx->index_buffer.buffer) {
+ draw.index_size = rctx->index_buffer.index_size;
+ draw.index_buffer = rctx->index_buffer.buffer;
-void r600_draw_arrays(struct pipe_context *ctx, unsigned mode,
- unsigned start, unsigned count)
-{
- struct r600_draw draw;
-
- draw.ctx = ctx;
- draw.mode = mode;
- draw.start = start;
- draw.count = count;
- draw.index_size = 0;
- draw.index_buffer = NULL;
+ assert(rctx->index_buffer.offset %
+ rctx->index_buffer.index_size == 0);
+ draw.start += rctx->index_buffer.offset /
+ rctx->index_buffer.index_size;
+ }
+ else {
+ draw.index_size = 0;
+ draw.index_buffer = NULL;
+ }
r600_draw_common(&draw);
}
diff --git a/src/gallium/drivers/r600/r600_helper.c b/src/gallium/drivers/r600/r600_helper.c
index e3175b627a..5e0e0aab57 100644
--- a/src/gallium/drivers/r600/r600_helper.c
+++ b/src/gallium/drivers/r600/r600_helper.c
@@ -27,95 +27,9 @@
#include <errno.h>
#include <util/u_inlines.h>
#include "r600_screen.h"
+#include "r600_context.h"
#include "r600d.h"
-int r600_conv_pipe_format(unsigned pformat, unsigned *format)
-{
- switch (pformat) {
- case PIPE_FORMAT_R32G32B32_FLOAT:
- *format = 0x30;
- return 0;
- case PIPE_FORMAT_R32G32B32A32_FLOAT:
- *format = V_0280A0_COLOR_32_32_32_32_FLOAT;
- return 0;
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_B8G8R8X8_UNORM:
- case PIPE_FORMAT_R8G8B8A8_UNORM:
- case PIPE_FORMAT_R8G8B8X8_UNORM:
- case PIPE_FORMAT_R8G8B8A8_USCALED:
- case PIPE_FORMAT_R8G8B8A8_SNORM:
- case PIPE_FORMAT_R8G8B8A8_SSCALED:
- *format = V_0280A0_COLOR_8_8_8_8;
- return 0;
- case PIPE_FORMAT_L8_UNORM:
- case PIPE_FORMAT_A8_UNORM:
- case PIPE_FORMAT_I8_UNORM:
- case PIPE_FORMAT_L16_UNORM:
- case PIPE_FORMAT_Z16_UNORM:
- case PIPE_FORMAT_Z32_UNORM:
- case PIPE_FORMAT_Z32_FLOAT:
- case PIPE_FORMAT_R64_FLOAT:
- case PIPE_FORMAT_R64G64_FLOAT:
- case PIPE_FORMAT_R64G64B64_FLOAT:
- case PIPE_FORMAT_R64G64B64A64_FLOAT:
- case PIPE_FORMAT_R32_FLOAT:
- case PIPE_FORMAT_R32G32_FLOAT:
- case PIPE_FORMAT_R32_UNORM:
- case PIPE_FORMAT_R32G32_UNORM:
- case PIPE_FORMAT_R32G32B32_UNORM:
- case PIPE_FORMAT_R32G32B32A32_UNORM:
- case PIPE_FORMAT_R32_USCALED:
- case PIPE_FORMAT_R32G32_USCALED:
- case PIPE_FORMAT_R32G32B32_USCALED:
- case PIPE_FORMAT_R32G32B32A32_USCALED:
- case PIPE_FORMAT_R32_SNORM:
- case PIPE_FORMAT_R32G32_SNORM:
- case PIPE_FORMAT_R32G32B32_SNORM:
- case PIPE_FORMAT_R32G32B32A32_SNORM:
- case PIPE_FORMAT_R32_SSCALED:
- case PIPE_FORMAT_R32G32_SSCALED:
- case PIPE_FORMAT_R32G32B32_SSCALED:
- case PIPE_FORMAT_R32G32B32A32_SSCALED:
- case PIPE_FORMAT_R16_UNORM:
- case PIPE_FORMAT_R16G16_UNORM:
- case PIPE_FORMAT_R16G16B16_UNORM:
- case PIPE_FORMAT_R16G16B16A16_UNORM:
- case PIPE_FORMAT_R16_USCALED:
- case PIPE_FORMAT_R16G16_USCALED:
- case PIPE_FORMAT_R16G16B16_USCALED:
- case PIPE_FORMAT_R16G16B16A16_USCALED:
- case PIPE_FORMAT_R16_SNORM:
- case PIPE_FORMAT_R16G16_SNORM:
- case PIPE_FORMAT_R16G16B16_SNORM:
- case PIPE_FORMAT_R16G16B16A16_SNORM:
- case PIPE_FORMAT_R16_SSCALED:
- case PIPE_FORMAT_R16G16_SSCALED:
- case PIPE_FORMAT_R16G16B16_SSCALED:
- case PIPE_FORMAT_R16G16B16A16_SSCALED:
- case PIPE_FORMAT_R8_UNORM:
- case PIPE_FORMAT_R8G8_UNORM:
- case PIPE_FORMAT_R8G8B8_UNORM:
- case PIPE_FORMAT_R8_USCALED:
- case PIPE_FORMAT_R8G8_USCALED:
- case PIPE_FORMAT_R8G8B8_USCALED:
- case PIPE_FORMAT_R8_SNORM:
- case PIPE_FORMAT_R8G8_SNORM:
- case PIPE_FORMAT_R8G8B8_SNORM:
- case PIPE_FORMAT_R8_SSCALED:
- case PIPE_FORMAT_R8G8_SSCALED:
- case PIPE_FORMAT_R8G8B8_SSCALED:
- case PIPE_FORMAT_R32_FIXED:
- case PIPE_FORMAT_R32G32_FIXED:
- case PIPE_FORMAT_R32G32B32_FIXED:
- case PIPE_FORMAT_R32G32B32A32_FIXED:
- default:
- fprintf(stderr, "%s:%d unsupported %d\n", __func__, __LINE__, pformat);
- return -EINVAL;
- }
-}
-
int r600_conv_pipe_prim(unsigned pprim, unsigned *prim)
{
switch (pprim) {
diff --git a/src/gallium/drivers/r600/r600_resource.c b/src/gallium/drivers/r600/r600_resource.c
index d9aa1df04f..8dc411ef40 100644
--- a/src/gallium/drivers/r600/r600_resource.c
+++ b/src/gallium/drivers/r600/r600_resource.c
@@ -24,45 +24,44 @@
#include "r600_context.h"
#include "r600_resource.h"
#include "r600_screen.h"
-#include "r600_texture.h"
-static struct pipe_resource *
-r600_resource_create(struct pipe_screen *screen,
- const struct pipe_resource *templ)
+static struct pipe_resource *r600_resource_create(struct pipe_screen *screen,
+ const struct pipe_resource *templ)
{
- if (templ->target == PIPE_BUFFER)
- return r600_buffer_create(screen, templ);
- else
- return r600_texture_create(screen, templ);
+ if (templ->target == PIPE_BUFFER) {
+ return r600_buffer_create(screen, templ);
+ } else {
+ return r600_texture_create(screen, templ);
+ }
}
-static struct pipe_resource *
-r600_resource_from_handle(struct pipe_screen * screen,
- const struct pipe_resource *templ,
- struct winsys_handle *whandle)
+static struct pipe_resource *r600_resource_from_handle(struct pipe_screen * screen,
+ const struct pipe_resource *templ,
+ struct winsys_handle *whandle)
{
- if (templ->target == PIPE_BUFFER)
- return NULL;
- else
- return r600_texture_from_handle(screen, templ, whandle);
+ if (templ->target == PIPE_BUFFER) {
+ return NULL;
+ } else {
+ return r600_texture_from_handle(screen, templ, whandle);
+ }
}
void r600_init_context_resource_functions(struct r600_context *r600)
{
- r600->context.get_transfer = u_get_transfer_vtbl;
- r600->context.transfer_map = u_transfer_map_vtbl;
- r600->context.transfer_flush_region = u_transfer_flush_region_vtbl;
- r600->context.transfer_unmap = u_transfer_unmap_vtbl;
- r600->context.transfer_destroy = u_transfer_destroy_vtbl;
- r600->context.transfer_inline_write = u_transfer_inline_write_vtbl;
- r600->context.is_resource_referenced = u_is_resource_referenced_vtbl;
+ r600->context.get_transfer = u_get_transfer_vtbl;
+ r600->context.transfer_map = u_transfer_map_vtbl;
+ r600->context.transfer_flush_region = u_transfer_flush_region_vtbl;
+ r600->context.transfer_unmap = u_transfer_unmap_vtbl;
+ r600->context.transfer_destroy = u_transfer_destroy_vtbl;
+ r600->context.transfer_inline_write = u_transfer_inline_write_vtbl;
+ r600->context.is_resource_referenced = u_is_resource_referenced_vtbl;
}
void r600_init_screen_resource_functions(struct r600_screen *r600screen)
{
- r600screen->screen.resource_create = r600_resource_create;
- r600screen->screen.resource_from_handle = r600_resource_from_handle;
- r600screen->screen.resource_get_handle = u_resource_get_handle_vtbl;
- r600screen->screen.resource_destroy = u_resource_destroy_vtbl;
- r600screen->screen.user_buffer_create = r600_user_buffer_create;
+ r600screen->screen.resource_create = r600_resource_create;
+ r600screen->screen.resource_from_handle = r600_resource_from_handle;
+ r600screen->screen.resource_get_handle = u_resource_get_handle_vtbl;
+ r600screen->screen.resource_destroy = u_resource_destroy_vtbl;
+ r600screen->screen.user_buffer_create = r600_user_buffer_create;
}
diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h
index 95084a371b..bb90e76fb7 100644
--- a/src/gallium/drivers/r600/r600_resource.h
+++ b/src/gallium/drivers/r600/r600_resource.h
@@ -20,14 +20,47 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-
#ifndef R600_RESOURCE_H
#define R600_RESOURCE_H
+#include "util/u_transfer.h"
+
struct r600_context;
struct r600_screen;
+/* This gets further specialized into either buffer or texture
+ * structures. Use the vtbl struct to choose between the two
+ * underlying implementations.
+ */
+struct r600_resource {
+ struct u_resource base;
+ struct radeon_bo *bo;
+ u32 domain;
+ u32 flink;
+ struct pb_buffer *pb;
+};
+
+struct r600_resource_texture {
+ struct r600_resource resource;
+ unsigned long offset[PIPE_MAX_TEXTURE_LEVELS];
+ unsigned long pitch[PIPE_MAX_TEXTURE_LEVELS];
+ unsigned long layer_size[PIPE_MAX_TEXTURE_LEVELS];
+ unsigned long pitch_override;
+ unsigned long bpt;
+ unsigned long size;
+};
+
void r600_init_context_resource_functions(struct r600_context *r600);
void r600_init_screen_resource_functions(struct r600_screen *r600screen);
+/* r600_buffer */
+u32 r600_domain_from_usage(unsigned usage);
+
+/* r600_texture */
+struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
+ const struct pipe_resource *templ);
+struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
+ const struct pipe_resource *base,
+ struct winsys_handle *whandle);
+
#endif
diff --git a/src/gallium/drivers/r600/r600_screen.c b/src/gallium/drivers/r600/r600_screen.c
index dec6fa8d27..cdaca9ed7d 100644
--- a/src/gallium/drivers/r600/r600_screen.c
+++ b/src/gallium/drivers/r600/r600_screen.c
@@ -24,15 +24,15 @@
* Jerome Glisse
* Corbin Simpson
*/
-#include <util/u_inlines.h>
-#include <util/u_format.h>
-#include <util/u_memory.h>
-#include "r600_resource.h"
+#include <stdio.h>
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "util/u_memory.h"
#include "r600_screen.h"
-#include "r600_texture.h"
#include "r600_context.h"
#include "r600_public.h"
-#include <stdio.h>
+#include "r600_resource.h"
+#include "r600_state_inlines.h"
static const char* r600_get_vendor(struct pipe_screen* pscreen)
{
@@ -53,61 +53,102 @@ static const char* r600_get_name(struct pipe_screen* pscreen)
static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
{
switch (param) {
- case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
- case PIPE_CAP_MAX_COMBINED_SAMPLERS:
- return 16;
+ /* Supported features (boolean caps). */
case PIPE_CAP_NPOT_TEXTURES:
- return 1;
case PIPE_CAP_TWO_SIDED_STENCIL:
- return 1;
case PIPE_CAP_GLSL:
- return 1;
case PIPE_CAP_DUAL_SOURCE_BLEND:
- return 1;
case PIPE_CAP_ANISOTROPIC_FILTER:
- return 1;
case PIPE_CAP_POINT_SPRITE:
- return 1;
- case PIPE_CAP_MAX_RENDER_TARGETS:
- /* FIXME some r6xx are buggy and can only do 4 */
- return 8;
case PIPE_CAP_OCCLUSION_QUERY:
- return 1;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
- return 1;
- case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
- case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
- case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
- /* FIXME not sure here */
- return 13;
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
- return 1;
case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
- return 1;
- case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
- /* FIXME allow this once infrastructure is there */
- return 0;
- case PIPE_CAP_TGSI_CONT_SUPPORTED:
- return 0;
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
- return 1;
case PIPE_CAP_SM3:
- return 1;
+ case PIPE_CAP_TEXTURE_SWIZZLE:
case PIPE_CAP_INDEP_BLEND_ENABLE:
- return 1;
- case PIPE_CAP_INDEP_BLEND_FUNC:
- /* FIXME allow this */
- return 0;
case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
return 1;
+
+ /* Unsupported features (boolean caps). */
+ case PIPE_CAP_TIMER_QUERY:
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ case PIPE_CAP_STREAM_OUTPUT:
+ case PIPE_CAP_INDEP_BLEND_FUNC: /* FIXME allow this */
+ case PIPE_CAP_GEOMETRY_SHADER4:
+ case PIPE_CAP_DEPTH_CLAMP: /* FIXME allow this */
+ return 0;
+
+ /* Texturing. */
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 14;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ /* FIXME allow this once infrastructure is there */
+ return 0;
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ case PIPE_CAP_MAX_COMBINED_SAMPLERS:
+ return 16;
+
+ /* Render targets. */
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ /* FIXME some r6xx are buggy and can only do 4 */
+ return 8;
+
+ /* Fragment coordinate conventions. */
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
return 1;
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
return 0;
+
+ /* Shader limits. */
+ case PIPE_CAP_MAX_VS_INSTRUCTIONS:
+ return 16384; //max native instructions, not greater than max instructions
+ case PIPE_CAP_MAX_VS_ALU_INSTRUCTIONS:
+ case PIPE_CAP_MAX_VS_TEX_INSTRUCTIONS:
+ case PIPE_CAP_MAX_VS_TEX_INDIRECTIONS:
+ return 16384;
+ case PIPE_CAP_MAX_FS_INSTRUCTIONS:
+ return 16384; //max program native instructions
+ case PIPE_CAP_MAX_FS_ALU_INSTRUCTIONS:
+ return 16384; //max program native ALU instructions
+ case PIPE_CAP_MAX_FS_TEX_INSTRUCTIONS:
+ return 16384; //max program native texture instructions
+ case PIPE_CAP_MAX_FS_TEX_INDIRECTIONS:
+ return 2048; //max program native texture indirections
+ case PIPE_CAP_MAX_VS_CONTROL_FLOW_DEPTH:
+ case PIPE_CAP_MAX_FS_CONTROL_FLOW_DEPTH:
+ return 8; /* FIXME */
+ case PIPE_CAP_MAX_VS_INPUTS:
+ return 16; //max native attributes
+ case PIPE_CAP_MAX_FS_INPUTS:
+ return 10; //max native attributes
+ case PIPE_CAP_MAX_VS_TEMPS:
+ return 256; //max native temporaries
+ case PIPE_CAP_MAX_FS_TEMPS:
+ return 256; //max native temporaries
+ case PIPE_CAP_MAX_VS_ADDRS:
+ case PIPE_CAP_MAX_FS_ADDRS:
+ return 1; //max native address registers/* FIXME Isn't this equal to TEMPS? */
+ case PIPE_CAP_MAX_VS_CONSTS:
+ return 256; //max native parameters
+ case PIPE_CAP_MAX_FS_CONSTS:
+ return 256; //max program native parameters
+ case PIPE_CAP_MAX_CONST_BUFFERS:
+ return 1;
+ case PIPE_CAP_MAX_CONST_BUFFER_SIZE: /* in bytes */
+ return 4096;
+ case PIPE_CAP_MAX_PREDICATE_REGISTERS:
+ case PIPE_CAP_MAX_VS_PREDS:
+ case PIPE_CAP_MAX_FS_PREDS:
+ return 0; /* FIXME */
+
default:
- debug_printf("r600: unknown param %d\n", param);
+ R600_ERR("r600: unknown param %d\n", param);
return 0;
}
}
@@ -125,7 +166,7 @@ static float r600_get_paramf(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
return 16.0f;
default:
- debug_printf("r600: unsupported paramf %d\n", param);
+ R600_ERR("r600: unsupported paramf %d\n", param);
return 0.0f;
}
}
@@ -134,108 +175,51 @@ static boolean r600_is_format_supported(struct pipe_screen* screen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
- unsigned bindings,
+ unsigned usage,
unsigned geom_flags)
{
+ unsigned retval = 0;
if (target >= PIPE_MAX_TEXTURE_TYPES) {
- debug_printf("r600: unsupported texture type %d\n", target);
+ R600_ERR("r600: unsupported texture type %d\n", target);
return FALSE;
}
- switch (format) {
- case PIPE_FORMAT_B4G4R4A4_UNORM:
- case PIPE_FORMAT_B5G6R5_UNORM:
- case PIPE_FORMAT_B5G5R5A1_UNORM:
- case PIPE_FORMAT_A8_UNORM:
- case PIPE_FORMAT_L8_UNORM:
- case PIPE_FORMAT_A8R8G8B8_SRGB:
- case PIPE_FORMAT_R8G8B8A8_SRGB:
- case PIPE_FORMAT_DXT1_RGB:
- case PIPE_FORMAT_DXT1_RGBA:
- case PIPE_FORMAT_DXT3_RGBA:
- case PIPE_FORMAT_DXT5_RGBA:
- case PIPE_FORMAT_UYVY:
- case PIPE_FORMAT_L8_SRGB:
- case PIPE_FORMAT_L8A8_SRGB:
- case PIPE_FORMAT_L8A8_UNORM:
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_R8G8B8A8_UNORM:
- case PIPE_FORMAT_R8G8B8X8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_B8G8R8X8_UNORM:
- case PIPE_FORMAT_A8B8G8R8_SRGB:
- case PIPE_FORMAT_B8G8R8A8_SRGB:
- case PIPE_FORMAT_I8_UNORM:
- case PIPE_FORMAT_Z16_UNORM:
- case PIPE_FORMAT_X8Z24_UNORM:
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- case PIPE_FORMAT_Z32_UNORM:
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- case PIPE_FORMAT_Z24X8_UNORM:
- return TRUE;
- default:
- /* Unknown format... */
- break;
- }
- return FALSE;
-}
-
-struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
- struct pipe_resource *texture,
- struct pipe_subresource sr,
- unsigned usage,
- const struct pipe_box *box)
-{
- struct r600_texture *rtex = (struct r600_texture*)texture;
- struct r600_transfer *trans;
- trans = CALLOC_STRUCT(r600_transfer);
- if (trans == NULL)
- return NULL;
- pipe_resource_reference(&trans->transfer.resource, texture);
- trans->transfer.sr = sr;
- trans->transfer.usage = usage;
- trans->transfer.box = *box;
- trans->transfer.stride = rtex->stride[sr.level];
- trans->offset = r600_texture_get_offset(rtex, sr.level, box->z, sr.face);
- return &trans->transfer;
-}
-
-void r600_texture_transfer_destroy(struct pipe_context *ctx,
- struct pipe_transfer *trans)
-{
- pipe_resource_reference(&trans->resource, NULL);
- FREE(trans);
-}
+ /* Multisample */
+ if (sample_count > 1)
+ return FALSE;
-void* r600_texture_transfer_map(struct pipe_context *ctx,
- struct pipe_transfer* transfer)
-{
- struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
- struct r600_texture *rtex = (struct r600_texture*)transfer->resource;
- char *map;
- enum pipe_format format = rtex->b.b.format;
+ if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
+ r600_is_sampler_format_supported(format)) {
+ retval |= PIPE_BIND_SAMPLER_VIEW;
+ }
- map = pipe_buffer_map(ctx, rtex->buffer,
- transfer->usage,
- &rtransfer->buffer_transfer);
+ if ((usage & (PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SCANOUT |
+ PIPE_BIND_SHARED)) &&
+ r600_is_colorbuffer_format_supported(format)) {
+ retval |= usage &
+ (PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SCANOUT |
+ PIPE_BIND_SHARED);
+ }
- if (!map) {
- return NULL;
+ if ((usage & PIPE_BIND_DEPTH_STENCIL) &&
+ r600_is_zs_format_supported(format)) {
+ retval |= PIPE_BIND_DEPTH_STENCIL;
}
- return map + rtransfer->offset +
- transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
- transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
-}
+ if ((usage & PIPE_BIND_VERTEX_BUFFER) &&
+ r600_is_vertex_format_supported(format))
+ retval |= PIPE_BIND_VERTEX_BUFFER;
-void r600_texture_transfer_unmap(struct pipe_context *ctx,
- struct pipe_transfer* transfer)
-{
- struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
- struct r600_texture *rtex = (struct r600_texture*)transfer->resource;
+ if (usage & PIPE_BIND_TRANSFER_READ)
+ retval |= PIPE_BIND_TRANSFER_READ;
+ if (usage & PIPE_BIND_TRANSFER_WRITE)
+ retval |= PIPE_BIND_TRANSFER_WRITE;
- pipe_buffer_unmap(ctx, rtex->buffer, rtransfer->buffer_transfer);
+ return retval == usage;
}
static void r600_destroy_screen(struct pipe_screen* pscreen)
diff --git a/src/gallium/drivers/r600/r600_screen.h b/src/gallium/drivers/r600/r600_screen.h
index 0a0286d96b..53b560c617 100644
--- a/src/gallium/drivers/r600/r600_screen.h
+++ b/src/gallium/drivers/r600/r600_screen.h
@@ -40,14 +40,6 @@ struct r600_transfer {
unsigned offset;
};
-struct r600_buffer {
- struct u_resource b;
- struct radeon_bo *bo;
- u32 domain;
- u32 flink;
- struct pb_buffer *pb;
-};
-
struct r600_screen {
struct pipe_screen screen;
struct radeon *rw;
@@ -88,17 +80,6 @@ void r600_texture_transfer_unmap(struct pipe_context *ctx,
int r600_conv_pipe_format(unsigned pformat, unsigned *format);
int r600_conv_pipe_prim(unsigned pprim, unsigned *prim);
-union r600_float_to_u32_u {
- u32 u;
- float f;
-};
-
-static inline u32 r600_float_to_u32(float f)
-{
- union r600_float_to_u32_u c;
-
- c.f = f;
- return c.u;
-}
+void r600_init_screen_texture_functions(struct pipe_screen *screen);
#endif
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index f7d6e10663..956c7e7930 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -19,78 +19,190 @@
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Jerome Glisse
*/
-#include <stdio.h>
-#include <errno.h>
-#include <util/u_inlines.h>
-#include <util/u_format.h>
-#include <util/u_memory.h>
-#include <tgsi/tgsi_dump.h>
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_scan.h"
+#include "tgsi/tgsi_dump.h"
+#include "util/u_format.h"
#include "r600_screen.h"
#include "r600_context.h"
+#include "r600_shader.h"
+#include "r600_asm.h"
+#include "r600_sq.h"
#include "r600d.h"
+#include <stdio.h>
+#include <errno.h>
+
+
+struct r600_shader_tgsi_instruction;
+
+struct r600_shader_ctx {
+ struct tgsi_shader_info info;
+ struct tgsi_parse_context parse;
+ const struct tgsi_token *tokens;
+ unsigned type;
+ unsigned file_offset[TGSI_FILE_COUNT];
+ unsigned temp_reg;
+ struct r600_shader_tgsi_instruction *inst_info;
+ struct r600_bc *bc;
+ struct r600_shader *shader;
+ u32 value[4];
+};
+
+struct r600_shader_tgsi_instruction {
+ unsigned tgsi_opcode;
+ unsigned is_op3;
+ unsigned r600_opcode;
+ int (*process)(struct r600_shader_ctx *ctx);
+};
+
+static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[];
+static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader);
+
+static int r600_shader_update(struct pipe_context *ctx, struct r600_shader *shader)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ const struct util_format_description *desc;
+ enum pipe_format resource_format[160];
+ unsigned i, nresources = 0;
+ struct r600_bc *bc = &shader->bc;
+ struct r600_bc_cf *cf;
+ struct r600_bc_vtx *vtx;
+
+ if (shader->processor_type != TGSI_PROCESSOR_VERTEX)
+ return 0;
+ for (i = 0; i < rctx->vertex_elements->count; i++) {
+ resource_format[nresources++] = rctx->vertex_elements->elements[i].src_format;
+ }
+ LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) {
+ switch (cf->inst) {
+ case V_SQ_CF_WORD1_SQ_CF_INST_VTX:
+ case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC:
+ LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) {
+ desc = util_format_description(resource_format[vtx->buffer_id]);
+ if (desc == NULL) {
+ R600_ERR("unknown format %d\n", resource_format[vtx->buffer_id]);
+ return -EINVAL;
+ }
+ vtx->dst_sel_x = desc->swizzle[0];
+ vtx->dst_sel_y = desc->swizzle[1];
+ vtx->dst_sel_z = desc->swizzle[2];
+ vtx->dst_sel_w = desc->swizzle[3];
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return r600_bc_build(&shader->bc);
+}
+
+int r600_pipe_shader_create(struct pipe_context *ctx,
+ struct r600_context_state *rpshader,
+ const struct tgsi_token *tokens)
+{
+ struct r600_screen *rscreen = r600_screen(ctx->screen);
+ int r;
+
+fprintf(stderr, "--------------------------------------------------------------\n");
+tgsi_dump(tokens, 0);
+ if (rpshader == NULL)
+ return -ENOMEM;
+ rpshader->shader.family = radeon_get_family(rscreen->rw);
+ r = r600_shader_from_tgsi(tokens, &rpshader->shader);
+ if (r) {
+ R600_ERR("translation from TGSI failed !\n");
+ return r;
+ }
+ r = r600_bc_build(&rpshader->shader.bc);
+ if (r) {
+ R600_ERR("building bytecode failed !\n");
+ return r;
+ }
+fprintf(stderr, "______________________________________________________________\n");
+ return 0;
+}
-static int r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
+static int r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_context_state *rpshader)
{
struct r600_screen *rscreen = r600_screen(ctx->screen);
struct r600_shader *rshader = &rpshader->shader;
struct radeon_state *state;
unsigned i, tmp;
- rpshader->state = radeon_state_decref(rpshader->state);
+ rpshader->rstate = radeon_state_decref(rpshader->rstate);
state = radeon_state(rscreen->rw, R600_VS_SHADER_TYPE, R600_VS_SHADER);
if (state == NULL)
return -ENOMEM;
- for (i = 0; i < rshader->noutput; i += 4) {
- tmp = rshader->output[i].sid;
- tmp |= rshader->output[i + 1].sid << 8;
- tmp |= rshader->output[i + 2].sid << 16;
- tmp |= rshader->output[i + 3].sid << 24;
- state->states[R600_VS_SHADER__SPI_VS_OUT_ID_0 + i / 4] = tmp;
- }
- state->states[R600_VS_SHADER__SPI_VS_OUT_CONFIG] = S_0286C4_VS_EXPORT_COUNT(rshader->noutput - 1);
- state->states[R600_VS_SHADER__SQ_PGM_RESOURCES_VS] = S_028868_NUM_GPRS(rshader->ngpr);
- rpshader->state = state;
- rpshader->state->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo);
- rpshader->state->bo[1] = radeon_bo_incref(rscreen->rw, rpshader->bo);
- rpshader->state->nbo = 2;
- rpshader->state->placement[0] = RADEON_GEM_DOMAIN_GTT;
+ for (i = 0; i < 10; i++) {
+ state->states[R600_VS_SHADER__SPI_VS_OUT_ID_0 + i] = 0;
+ }
+ /* so far never got proper semantic id from tgsi */
+ for (i = 0; i < 32; i++) {
+ tmp = i << ((i & 3) * 8);
+ state->states[R600_VS_SHADER__SPI_VS_OUT_ID_0 + i / 4] |= tmp;
+ }
+ state->states[R600_VS_SHADER__SPI_VS_OUT_CONFIG] = S_0286C4_VS_EXPORT_COUNT(rshader->noutput - 2);
+ state->states[R600_VS_SHADER__SQ_PGM_RESOURCES_VS] = S_028868_NUM_GPRS(rshader->bc.ngpr);
+ rpshader->rstate = state;
+ rpshader->rstate->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo);
+ rpshader->rstate->bo[1] = radeon_bo_incref(rscreen->rw, rpshader->bo);
+ rpshader->rstate->nbo = 2;
+ rpshader->rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
return radeon_state_pm4(state);
}
-static int r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
+static int r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_context_state *rpshader)
{
+ const struct pipe_rasterizer_state *rasterizer;
struct r600_screen *rscreen = r600_screen(ctx->screen);
struct r600_shader *rshader = &rpshader->shader;
+ struct r600_context *rctx = r600_context(ctx);
struct radeon_state *state;
- unsigned i, tmp;
+ unsigned i, tmp, exports_ps, num_cout;
- rpshader->state = radeon_state_decref(rpshader->state);
+ rasterizer = &rctx->rasterizer->state.rasterizer;
+ rpshader->rstate = radeon_state_decref(rpshader->rstate);
state = radeon_state(rscreen->rw, R600_PS_SHADER_TYPE, R600_PS_SHADER);
if (state == NULL)
return -ENOMEM;
for (i = 0; i < rshader->ninput; i++) {
- tmp = S_028644_SEMANTIC(rshader->input[i].sid);
+ tmp = S_028644_SEMANTIC(i);
tmp |= S_028644_SEL_CENTROID(1);
- tmp |= S_028644_FLAT_SHADE(rshader->flat_shade);
+ if (rshader->input[i].name == TGSI_SEMANTIC_COLOR ||
+ rshader->input[i].name == TGSI_SEMANTIC_BCOLOR) {
+ tmp |= S_028644_FLAT_SHADE(rshader->flat_shade);
+ }
+ if (rasterizer->sprite_coord_enable & (1 << i)) {
+ tmp |= S_028644_PT_SPRITE_TEX(1);
+ }
state->states[R600_PS_SHADER__SPI_PS_INPUT_CNTL_0 + i] = tmp;
}
+
+ exports_ps = 0;
+ num_cout = 0;
+ for (i = 0; i < rshader->noutput; i++) {
+ if (rshader->output[i].name == TGSI_SEMANTIC_POSITION)
+ exports_ps |= 1;
+ else if (rshader->output[i].name == TGSI_SEMANTIC_COLOR) {
+ exports_ps |= (1 << (num_cout+1));
+ num_cout++;
+ }
+ }
state->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_0] = S_0286CC_NUM_INTERP(rshader->ninput) |
S_0286CC_PERSP_GRADIENT_ENA(1);
state->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_1] = 0x00000000;
- state->states[R600_PS_SHADER__SQ_PGM_RESOURCES_PS] = S_028868_NUM_GPRS(rshader->ngpr);
- state->states[R600_PS_SHADER__SQ_PGM_EXPORTS_PS] = 0x00000002;
- rpshader->state = state;
- rpshader->state->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo);
- rpshader->state->nbo = 1;
- rpshader->state->placement[0] = RADEON_GEM_DOMAIN_GTT;
+ state->states[R600_PS_SHADER__SQ_PGM_RESOURCES_PS] = S_028868_NUM_GPRS(rshader->bc.ngpr);
+ state->states[R600_PS_SHADER__SQ_PGM_EXPORTS_PS] = exports_ps;
+ rpshader->rstate = state;
+ rpshader->rstate->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo);
+ rpshader->rstate->nbo = 1;
+ rpshader->rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
return radeon_state_pm4(state);
}
-static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
+static int r600_pipe_shader(struct pipe_context *ctx, struct r600_context_state *rpshader)
{
struct r600_screen *rscreen = r600_screen(ctx->screen);
struct r600_context *rctx = r600_context(ctx);
@@ -100,21 +212,21 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *r
/* copy new shader */
radeon_bo_decref(rscreen->rw, rpshader->bo);
rpshader->bo = NULL;
- rpshader->bo = radeon_bo(rscreen->rw, 0, rshader->ndw * 4,
+ rpshader->bo = radeon_bo(rscreen->rw, 0, rshader->bc.ndw * 4,
4096, NULL);
if (rpshader->bo == NULL) {
return -ENOMEM;
}
radeon_bo_map(rscreen->rw, rpshader->bo);
- memcpy(rpshader->bo->data, rshader->bcode, rshader->ndw * 4);
+ memcpy(rpshader->bo->data, rshader->bc.bytecode, rshader->bc.ndw * 4);
radeon_bo_unmap(rscreen->rw, rpshader->bo);
/* build state */
rshader->flat_shade = rctx->flat_shade;
- switch (rpshader->type) {
- case C_PROGRAM_TYPE_VS:
+ switch (rshader->processor_type) {
+ case TGSI_PROCESSOR_VERTEX:
r = r600_pipe_shader_vs(ctx, rpshader);
break;
- case C_PROGRAM_TYPE_FS:
+ case TGSI_PROCESSOR_FRAGMENT:
r = r600_pipe_shader_ps(ctx, rpshader);
break;
default:
@@ -124,104 +236,1129 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *r
return r;
}
-struct r600_pipe_shader *r600_pipe_shader_create(struct pipe_context *ctx, unsigned type, const struct tgsi_token *tokens)
+int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_context_state *rpshader)
{
- struct r600_screen *rscreen = r600_screen(ctx->screen);
- struct r600_pipe_shader *rpshader = CALLOC_STRUCT(r600_pipe_shader);
- struct r600_shader *rshader = &rpshader->shader;
+ struct r600_context *rctx = r600_context(ctx);
int r;
- enum radeon_family family;
if (rpshader == NULL)
- return NULL;
- rpshader->type = type;
- family = radeon_get_family(rscreen->rw);
- rshader->r6xx_compile = (family >= CHIP_R600 && family < CHIP_RV770);
- LIST_INITHEAD(&rshader->nodes);
- fprintf(stderr, "<< %s\n", rshader->r6xx_compile ? "R600" : "R700");
- tgsi_dump(tokens, 0);
- fprintf(stderr, "--------------------------------------------------------------\n");
- r = c_shader_from_tgsi(&rshader->cshader, type, tokens);
- if (r) {
- r600_pipe_shader_destroy(ctx, rpshader);
- fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
- return NULL;
+ return -EINVAL;
+ /* there should be enough input */
+ if (rctx->vertex_elements->count < rpshader->shader.bc.nresource) {
+ R600_ERR("%d resources provided, expecting %d\n",
+ rctx->vertex_elements->count, rpshader->shader.bc.nresource);
+ return -EINVAL;
}
- r = r600_shader_insert_fetch(&rshader->cshader);
- if (r) {
- r600_pipe_shader_destroy(ctx, rpshader);
- fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
- return NULL;
+ r = r600_shader_update(ctx, &rpshader->shader);
+ if (r)
+ return r;
+ return r600_pipe_shader(ctx, rpshader);
+}
+
+static int tgsi_is_supported(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *i = &ctx->parse.FullToken.FullInstruction;
+ int j;
+
+ if (i->Instruction.NumDstRegs > 1) {
+ R600_ERR("too many dst (%d)\n", i->Instruction.NumDstRegs);
+ return -EINVAL;
}
- r = c_shader_build_dominator_tree(&rshader->cshader);
- if (r) {
- r600_pipe_shader_destroy(ctx, rpshader);
- fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
- return NULL;
+ if (i->Instruction.Predicate) {
+ R600_ERR("predicate unsupported\n");
+ return -EINVAL;
}
- r = r600_cshader_legalize(&rshader->cshader);
- if (r) {
- r600_pipe_shader_destroy(ctx, rpshader);
- fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
- return NULL;
+ if (i->Instruction.Label) {
+ R600_ERR("label unsupported\n");
+ return -EINVAL;
}
- c_shader_dump(&rshader->cshader);
- r = r700_shader_translate(rshader);
- if (r) {
- r600_pipe_shader_destroy(ctx, rpshader);
- fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
- return NULL;
+ for (j = 0; j < i->Instruction.NumSrcRegs; j++) {
+ if (i->Src[j].Register.Indirect ||
+ i->Src[j].Register.Dimension ||
+ i->Src[j].Register.Absolute) {
+ R600_ERR("unsupported src (indirect|dimension|absolute)\n");
+ return -EINVAL;
+ }
}
-#if 1
-#if 0
- fprintf(stderr, "--------------------------------------------------------------\n");
- for (int i = 0; i < rshader->ndw; i++) {
- fprintf(stderr, "0x%08X\n", rshader->bcode[i]);
+ for (j = 0; j < i->Instruction.NumDstRegs; j++) {
+ if (i->Dst[j].Register.Indirect || i->Dst[j].Register.Dimension) {
+ R600_ERR("unsupported dst (indirect|dimension)\n");
+ return -EINVAL;
+ }
}
-#endif
- fprintf(stderr, ">>\n\n");
-#endif
- return rpshader;
+ return 0;
}
-void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
+static int tgsi_declaration(struct r600_shader_ctx *ctx)
{
- struct r600_screen *rscreen = r600_screen(ctx->screen);
+ struct tgsi_full_declaration *d = &ctx->parse.FullToken.FullDeclaration;
+ struct r600_bc_vtx vtx;
+ unsigned i;
+ int r;
- if (rpshader == NULL)
- return;
- radeon_bo_decref(rscreen->rw, rpshader->bo);
- rpshader->bo = NULL;
- r600_shader_cleanup(&rpshader->shader);
- FREE(rpshader);
+ switch (d->Declaration.File) {
+ case TGSI_FILE_INPUT:
+ i = ctx->shader->ninput++;
+ ctx->shader->input[i].name = d->Semantic.Name;
+ ctx->shader->input[i].sid = d->Semantic.Index;
+ ctx->shader->input[i].interpolate = d->Declaration.Interpolate;
+ ctx->shader->input[i].gpr = ctx->file_offset[TGSI_FILE_INPUT] + i;
+ if (ctx->type == TGSI_PROCESSOR_VERTEX) {
+ /* turn input into fetch */
+ memset(&vtx, 0, sizeof(struct r600_bc_vtx));
+ vtx.inst = 0;
+ vtx.fetch_type = 0;
+ vtx.buffer_id = i;
+ /* register containing the index into the buffer */
+ vtx.src_gpr = 0;
+ vtx.src_sel_x = 0;
+ vtx.mega_fetch_count = 0x1F;
+ vtx.dst_gpr = ctx->shader->input[i].gpr;
+ vtx.dst_sel_x = 0;
+ vtx.dst_sel_y = 1;
+ vtx.dst_sel_z = 2;
+ vtx.dst_sel_w = 3;
+ r = r600_bc_add_vtx(ctx->bc, &vtx);
+ if (r)
+ return r;
+ }
+ break;
+ case TGSI_FILE_OUTPUT:
+ i = ctx->shader->noutput++;
+ ctx->shader->output[i].name = d->Semantic.Name;
+ ctx->shader->output[i].sid = d->Semantic.Index;
+ ctx->shader->output[i].gpr = ctx->file_offset[TGSI_FILE_OUTPUT] + i;
+ ctx->shader->output[i].interpolate = d->Declaration.Interpolate;
+ break;
+ case TGSI_FILE_CONSTANT:
+ case TGSI_FILE_TEMPORARY:
+ case TGSI_FILE_SAMPLER:
+ break;
+ default:
+ R600_ERR("unsupported file %d declaration\n", d->Declaration.File);
+ return -EINVAL;
+ }
+ return 0;
}
-int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
+int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader)
{
- struct r600_context *rctx = r600_context(ctx);
- struct r600_shader *rshader;
- enum pipe_format resource_format[160];
- unsigned i, nresources = 0;
- int r;
+ struct tgsi_full_immediate *immediate;
+ struct r600_shader_ctx ctx;
+ struct r600_bc_output output[32];
+ unsigned output_done, noutput;
+ unsigned opcode;
+ int i, r = 0, pos0;
- if (rpshader == NULL)
- return -EINVAL;
- rshader = &rpshader->shader;
- switch (rpshader->type) {
- case C_PROGRAM_TYPE_VS:
- for (i = 0; i < rctx->vertex_elements->count; i++) {
- resource_format[nresources++] = rctx->vertex_elements->elements[i].src_format;
+ ctx.bc = &shader->bc;
+ ctx.shader = shader;
+ r = r600_bc_init(ctx.bc, shader->family);
+ if (r)
+ return r;
+ ctx.tokens = tokens;
+ tgsi_scan_shader(tokens, &ctx.info);
+ tgsi_parse_init(&ctx.parse, tokens);
+ ctx.type = ctx.parse.FullHeader.Processor.Processor;
+ shader->processor_type = ctx.type;
+
+ /* register allocations */
+ /* Values [0,127] correspond to GPR[0..127].
+ * Values [256,511] correspond to cfile constants c[0..255].
+ * Other special values are shown in the list below.
+ * 248 SQ_ALU_SRC_0: special constant 0.0.
+ * 249 SQ_ALU_SRC_1: special constant 1.0 float.
+ * 250 SQ_ALU_SRC_1_INT: special constant 1 integer.
+ * 251 SQ_ALU_SRC_M_1_INT: special constant -1 integer.
+ * 252 SQ_ALU_SRC_0_5: special constant 0.5 float.
+ * 253 SQ_ALU_SRC_LITERAL: literal constant.
+ * 254 SQ_ALU_SRC_PV: previous vector result.
+ * 255 SQ_ALU_SRC_PS: previous scalar result.
+ */
+ for (i = 0; i < TGSI_FILE_COUNT; i++) {
+ ctx.file_offset[i] = 0;
+ }
+ if (ctx.type == TGSI_PROCESSOR_VERTEX) {
+ ctx.file_offset[TGSI_FILE_INPUT] = 1;
+ }
+ ctx.file_offset[TGSI_FILE_OUTPUT] = ctx.file_offset[TGSI_FILE_INPUT] +
+ ctx.info.file_count[TGSI_FILE_INPUT];
+ ctx.file_offset[TGSI_FILE_TEMPORARY] = ctx.file_offset[TGSI_FILE_OUTPUT] +
+ ctx.info.file_count[TGSI_FILE_OUTPUT];
+ ctx.file_offset[TGSI_FILE_CONSTANT] = 256;
+ ctx.file_offset[TGSI_FILE_IMMEDIATE] = 253;
+ ctx.temp_reg = ctx.file_offset[TGSI_FILE_TEMPORARY] +
+ ctx.info.file_count[TGSI_FILE_TEMPORARY];
+
+ while (!tgsi_parse_end_of_tokens(&ctx.parse)) {
+ tgsi_parse_token(&ctx.parse);
+ switch (ctx.parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ immediate = &ctx.parse.FullToken.FullImmediate;
+ ctx.value[0] = immediate->u[0].Uint;
+ ctx.value[1] = immediate->u[1].Uint;
+ ctx.value[2] = immediate->u[2].Uint;
+ ctx.value[3] = immediate->u[3].Uint;
+ break;
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ r = tgsi_declaration(&ctx);
+ if (r)
+ goto out_err;
+ break;
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ r = tgsi_is_supported(&ctx);
+ if (r)
+ goto out_err;
+ opcode = ctx.parse.FullToken.FullInstruction.Instruction.Opcode;
+ ctx.inst_info = &r600_shader_tgsi_instruction[opcode];
+ r = ctx.inst_info->process(&ctx);
+ if (r)
+ goto out_err;
+ r = r600_bc_add_literal(ctx.bc, ctx.value);
+ if (r)
+ goto out_err;
+ break;
+ default:
+ R600_ERR("unsupported token type %d\n", ctx.parse.FullToken.Token.Type);
+ r = -EINVAL;
+ goto out_err;
}
- break;
+ }
+ /* export output */
+ noutput = shader->noutput;
+ for (i = 0, pos0 = 0; i < noutput; i++) {
+ memset(&output[i], 0, sizeof(struct r600_bc_output));
+ output[i].gpr = shader->output[i].gpr;
+ output[i].elem_size = 3;
+ output[i].swizzle_x = 0;
+ output[i].swizzle_y = 1;
+ output[i].swizzle_z = 2;
+ output[i].swizzle_w = 3;
+ output[i].barrier = 1;
+ output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
+ output[i].array_base = i - pos0;
+ output[i].inst = V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT;
+ switch (ctx.type) {
+ case TGSI_PROCESSOR_VERTEX:
+ if (shader->output[i].name == TGSI_SEMANTIC_POSITION) {
+ output[i].array_base = 60;
+ output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
+ /* position doesn't count in array_base */
+ pos0++;
+ }
+ if (shader->output[i].name == TGSI_SEMANTIC_PSIZE) {
+ output[i].array_base = 61;
+ output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
+ /* position doesn't count in array_base */
+ pos0++;
+ }
+ break;
+ case TGSI_PROCESSOR_FRAGMENT:
+ if (shader->output[i].name == TGSI_SEMANTIC_COLOR) {
+ output[i].array_base = shader->output[i].sid;
+ output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+ } else if (shader->output[i].name == TGSI_SEMANTIC_POSITION) {
+ output[i].array_base = 61;
+ output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+ } else {
+ R600_ERR("unsupported fragment output name %d\n", shader->output[i].name);
+ r = -EINVAL;
+ goto out_err;
+ }
+ break;
+ default:
+ R600_ERR("unsupported processor type %d\n", ctx.type);
+ r = -EINVAL;
+ goto out_err;
+ }
+ }
+ /* add fake param output for vertex shader if no param is exported */
+ if (ctx.type == TGSI_PROCESSOR_VERTEX) {
+ for (i = 0, pos0 = 0; i < noutput; i++) {
+ if (output[i].type == V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM) {
+ pos0 = 1;
+ break;
+ }
+ }
+ if (!pos0) {
+ memset(&output[i], 0, sizeof(struct r600_bc_output));
+ output[i].gpr = 0;
+ output[i].elem_size = 3;
+ output[i].swizzle_x = 0;
+ output[i].swizzle_y = 1;
+ output[i].swizzle_z = 2;
+ output[i].swizzle_w = 3;
+ output[i].barrier = 1;
+ output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
+ output[i].array_base = 0;
+ output[i].inst = V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT;
+ noutput++;
+ }
+ }
+ /* add fake pixel export */
+ if (ctx.type == TGSI_PROCESSOR_FRAGMENT && !noutput) {
+ memset(&output[0], 0, sizeof(struct r600_bc_output));
+ output[0].gpr = 0;
+ output[0].elem_size = 3;
+ output[0].swizzle_x = 7;
+ output[0].swizzle_y = 7;
+ output[0].swizzle_z = 7;
+ output[0].swizzle_w = 7;
+ output[0].barrier = 1;
+ output[0].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
+ output[0].array_base = 0;
+ output[0].inst = V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT;
+ noutput++;
+ }
+ /* set export done on last export of each type */
+ for (i = noutput - 1, output_done = 0; i >= 0; i--) {
+ if (i == (noutput - 1)) {
+ output[i].end_of_program = 1;
+ }
+ if (!(output_done & (1 << output[i].type))) {
+ output_done |= (1 << output[i].type);
+ output[i].inst = V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE;
+ }
+ }
+ /* add output to bytecode */
+ for (i = 0; i < noutput; i++) {
+ r = r600_bc_add_output(ctx.bc, &output[i]);
+ if (r)
+ goto out_err;
+ }
+ tgsi_parse_free(&ctx.parse);
+ return 0;
+out_err:
+ tgsi_parse_free(&ctx.parse);
+ return r;
+}
+
+static int tgsi_unsupported(struct r600_shader_ctx *ctx)
+{
+ R600_ERR("%d tgsi opcode unsupported\n", ctx->inst_info->tgsi_opcode);
+ return -EINVAL;
+}
+
+static int tgsi_end(struct r600_shader_ctx *ctx)
+{
+ return 0;
+}
+
+static int tgsi_src(struct r600_shader_ctx *ctx,
+ const struct tgsi_full_src_register *tgsi_src,
+ struct r600_bc_alu_src *r600_src)
+{
+ memset(r600_src, 0, sizeof(struct r600_bc_alu_src));
+ r600_src->sel = tgsi_src->Register.Index;
+ if (tgsi_src->Register.File == TGSI_FILE_IMMEDIATE) {
+ r600_src->sel = 0;
+ }
+ r600_src->neg = tgsi_src->Register.Negate;
+ r600_src->sel += ctx->file_offset[tgsi_src->Register.File];
+ return 0;
+}
+
+static int tgsi_dst(struct r600_shader_ctx *ctx,
+ const struct tgsi_full_dst_register *tgsi_dst,
+ unsigned swizzle,
+ struct r600_bc_alu_dst *r600_dst)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+
+ r600_dst->sel = tgsi_dst->Register.Index;
+ r600_dst->sel += ctx->file_offset[tgsi_dst->Register.File];
+ r600_dst->chan = swizzle;
+ r600_dst->write = 1;
+ if (inst->Instruction.Saturate) {
+ r600_dst->clamp = 1;
+ }
+ return 0;
+}
+
+static unsigned tgsi_chan(const struct tgsi_full_src_register *tgsi_src, unsigned swizzle)
+{
+ switch (swizzle) {
+ case 0:
+ return tgsi_src->Register.SwizzleX;
+ case 1:
+ return tgsi_src->Register.SwizzleY;
+ case 2:
+ return tgsi_src->Register.SwizzleZ;
+ case 3:
+ return tgsi_src->Register.SwizzleW;
default:
- break;
+ return 0;
}
- /* there should be enough input */
- if (nresources < rshader->nresource)
- return -EINVAL;
- /* FIXME compare resources */
- r = r600_shader_update(rshader, resource_format);
+}
+
+static int tgsi_split_constant(struct r600_shader_ctx *ctx, struct r600_bc_alu_src r600_src[3])
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_alu alu;
+ int i, j, k, nconst, r;
+
+ for (i = 0, nconst = 0; i < inst->Instruction.NumSrcRegs; i++) {
+ if (inst->Src[i].Register.File == TGSI_FILE_CONSTANT) {
+ nconst++;
+ }
+ r = tgsi_src(ctx, &inst->Src[i], &r600_src[i]);
+ if (r) {
+ return r;
+ }
+ }
+ for (i = 0, j = nconst - 1; i < inst->Instruction.NumSrcRegs; i++) {
+ if (inst->Src[j].Register.File == TGSI_FILE_CONSTANT && j > 0) {
+ for (k = 0; k < 4; k++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV;
+ alu.src[0].sel = r600_src[0].sel;
+ alu.src[0].chan = k;
+ alu.dst.sel = ctx->temp_reg + j;
+ alu.dst.chan = k;
+ alu.dst.write = 1;
+ if (k == 3)
+ alu.last = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ r600_src[0].sel = ctx->temp_reg + j;
+ j--;
+ }
+ }
+ return 0;
+}
+
+static int tgsi_op2(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_alu_src r600_src[3];
+ struct r600_bc_alu alu;
+ int i, j, r;
+
+ r = tgsi_split_constant(ctx, r600_src);
if (r)
return r;
- return r600_pipe_shader(ctx, rpshader);
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ if (!(inst->Dst[0].Register.WriteMask & (1 << i))) {
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
+ alu.dst.chan = i;
+ } else {
+ alu.inst = ctx->inst_info->r600_opcode;
+ for (j = 0; j < inst->Instruction.NumSrcRegs; j++) {
+ alu.src[j] = r600_src[j];
+ alu.src[j].chan = tgsi_chan(&inst->Src[j], i);
+ }
+ r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+ if (r)
+ return r;
+ }
+ /* handle some special cases */
+ switch (ctx->inst_info->tgsi_opcode) {
+ case TGSI_OPCODE_SUB:
+ alu.src[1].neg = 1;
+ break;
+ case TGSI_OPCODE_ABS:
+ alu.src[0].abs = 1;
+ break;
+ default:
+ break;
+ }
+ if (i == 3) {
+ alu.last = 1;
+ }
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ return 0;
+}
+
+static int tgsi_kill(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_alu alu;
+ int i, r;
+
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = ctx->inst_info->r600_opcode;
+ alu.dst.chan = i;
+ alu.src[0].sel = 248;
+ r = tgsi_src(ctx, &inst->Src[0], &alu.src[1]);
+ if (r)
+ return r;
+ alu.src[1].chan = tgsi_chan(&inst->Src[0], i);
+ if (i == 3) {
+ alu.last = 1;
+ }
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ return 0;
+}
+
+static int tgsi_slt(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_alu_src r600_src[3];
+ struct r600_bc_alu alu;
+ int i, r;
+
+ r = tgsi_split_constant(ctx, r600_src);
+ if (r)
+ return r;
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ if (!(inst->Dst[0].Register.WriteMask & (1 << i))) {
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
+ alu.dst.chan = i;
+ } else {
+ alu.inst = ctx->inst_info->r600_opcode;
+ alu.src[1] = r600_src[0];
+ alu.src[1].chan = tgsi_chan(&inst->Src[0], i);
+ alu.src[0] = r600_src[1];
+ alu.src[0].chan = tgsi_chan(&inst->Src[1], i);
+ r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+ if (r)
+ return r;
+ }
+ if (i == 3) {
+ alu.last = 1;
+ }
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ return 0;
+}
+
+static int tgsi_lit(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_alu alu;
+ int r;
+
+ /* dst.x, <- 1.0 */
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV;
+ alu.src[0].sel = 249; /*1.0*/
+ alu.src[0].chan = 0;
+ r = tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
+ if (r)
+ return r;
+ alu.dst.write = (inst->Dst[0].Register.WriteMask >> 0) & 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+
+ /* dst.y = max(src.x, 0.0) */
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX;
+ r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+ if (r)
+ return r;
+ alu.src[1].sel = 248; /*0.0*/
+ alu.src[1].chan = tgsi_chan(&inst->Src[0], 0);
+ r = tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
+ if (r)
+ return r;
+ alu.dst.write = (inst->Dst[0].Register.WriteMask >> 1) & 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+
+ /* dst.z = NOP - fill Z slot */
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
+ alu.dst.chan = 2;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+
+ /* dst.w, <- 1.0 */
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV;
+ alu.src[0].sel = 249;
+ alu.src[0].chan = 0;
+ r = tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst);
+ if (r)
+ return r;
+ alu.dst.write = (inst->Dst[0].Register.WriteMask >> 3) & 1;
+ alu.last = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+
+ if (inst->Dst[0].Register.WriteMask & (1 << 2))
+ {
+ int chan;
+ int sel;
+
+ /* dst.z = log(src.y) */
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_CLAMPED;
+ r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+ if (r)
+ return r;
+ alu.src[0].chan = tgsi_chan(&inst->Src[0], 1);
+ r = tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst);
+ if (r)
+ return r;
+ alu.last = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+
+ chan = alu.dst.chan;
+ sel = alu.dst.sel;
+
+ /* tmp.x = amd MUL_LIT(src.w, dst.z, src.x ) */
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT;
+ r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+ if (r)
+ return r;
+ alu.src[0].chan = tgsi_chan(&inst->Src[0], 3);
+ alu.src[1].sel = sel;
+ alu.src[1].chan = chan;
+ r = tgsi_src(ctx, &inst->Src[0], &alu.src[2]);
+ if (r)
+ return r;
+ alu.src[2].chan = tgsi_chan(&inst->Src[0], 0);
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = 0;
+ alu.dst.write = 1;
+ alu.is_op3 = 1;
+ alu.last = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+
+ /* dst.z = exp(tmp.x) */
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE;
+ alu.src[0].sel = ctx->temp_reg;
+ alu.src[0].chan = 0;
+ r = tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst);
+ if (r)
+ return r;
+ alu.last = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ return 0;
+}
+
+static int tgsi_trans(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_alu alu;
+ int i, j, r;
+
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ if (inst->Dst[0].Register.WriteMask & (1 << i)) {
+ alu.inst = ctx->inst_info->r600_opcode;
+ for (j = 0; j < inst->Instruction.NumSrcRegs; j++) {
+ r = tgsi_src(ctx, &inst->Src[j], &alu.src[j]);
+ if (r)
+ return r;
+ alu.src[j].chan = tgsi_chan(&inst->Src[j], i);
+ }
+ r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+ if (r)
+ return r;
+ alu.last = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ }
+ return 0;
+}
+
+static int tgsi_trans_srcx_replicate(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_alu alu;
+ int i, j, r;
+
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = ctx->inst_info->r600_opcode;
+ for (j = 0; j < inst->Instruction.NumSrcRegs; j++) {
+ r = tgsi_src(ctx, &inst->Src[j], &alu.src[j]);
+ if (r)
+ return r;
+ alu.src[j].chan = tgsi_chan(&inst->Src[j], 0);
+ }
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.write = 1;
+ alu.last = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ /* replicate result */
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.src[0].sel = ctx->temp_reg;
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV;
+ alu.dst.chan = i;
+ r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+ if (r)
+ return r;
+ alu.dst.write = (inst->Dst[0].Register.WriteMask >> i) & 1;
+ if (i == 3)
+ alu.last = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ return 0;
+}
+
+static int tgsi_helper_copy(struct r600_shader_ctx *ctx, struct tgsi_full_instruction *inst)
+{
+ struct r600_bc_alu alu;
+ int i, r;
+
+ r = r600_bc_add_literal(ctx->bc, ctx->value);
+ if (r)
+ return r;
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ if (!(inst->Dst[0].Register.WriteMask & (1 << i))) {
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
+ alu.dst.chan = i;
+ } else {
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV;
+ r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+ if (r)
+ return r;
+ alu.src[0].sel = ctx->temp_reg;
+ alu.src[0].chan = i;
+ }
+ if (i == 3) {
+ alu.last = 1;
+ }
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ return 0;
+}
+
+static int tgsi_op3(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_alu_src r600_src[3];
+ struct r600_bc_alu alu;
+ int i, j, r;
+
+ r = tgsi_split_constant(ctx, r600_src);
+ if (r)
+ return r;
+ /* do it in 2 step as op3 doesn't support writemask */
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = ctx->inst_info->r600_opcode;
+ for (j = 0; j < inst->Instruction.NumSrcRegs; j++) {
+ alu.src[j] = r600_src[j];
+ alu.src[j].chan = tgsi_chan(&inst->Src[j], i);
+ }
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = i;
+ alu.dst.write = 1;
+ alu.is_op3 = 1;
+ if (i == 3) {
+ alu.last = 1;
+ }
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ return tgsi_helper_copy(ctx, inst);
}
+
+static int tgsi_dp(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_alu_src r600_src[3];
+ struct r600_bc_alu alu;
+ int i, j, r;
+
+ r = tgsi_split_constant(ctx, r600_src);
+ if (r)
+ return r;
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = ctx->inst_info->r600_opcode;
+ for (j = 0; j < inst->Instruction.NumSrcRegs; j++) {
+ alu.src[j] = r600_src[j];
+ alu.src[j].chan = tgsi_chan(&inst->Src[j], i);
+ }
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = i;
+ alu.dst.write = 1;
+ /* handle some special cases */
+ switch (ctx->inst_info->tgsi_opcode) {
+ case TGSI_OPCODE_DP2:
+ if (i > 1) {
+ alu.src[0].sel = alu.src[1].sel = 248;
+ alu.src[0].chan = alu.src[1].chan = 0;
+ }
+ break;
+ case TGSI_OPCODE_DP3:
+ if (i > 2) {
+ alu.src[0].sel = alu.src[1].sel = 248;
+ alu.src[0].chan = alu.src[1].chan = 0;
+ }
+ break;
+ default:
+ break;
+ }
+ if (i == 3) {
+ alu.last = 1;
+ }
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ return tgsi_helper_copy(ctx, inst);
+}
+
+static int tgsi_tex(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_tex tex;
+ struct r600_bc_alu alu;
+ unsigned src_gpr;
+ int r;
+
+ src_gpr = ctx->file_offset[inst->Src[0].Register.File] + inst->Src[0].Register.Index;
+
+ /* Add perspective divide */
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE;
+ alu.src[0].sel = src_gpr;
+ alu.src[0].chan = tgsi_chan(&inst->Src[0], 3);
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = 3;
+ alu.last = 1;
+ alu.dst.write = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL;
+ alu.src[0].sel = ctx->temp_reg;
+ alu.src[0].chan = 3;
+ alu.src[1].sel = src_gpr;
+ alu.src[1].chan = tgsi_chan(&inst->Src[0], 0);
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = 0;
+ alu.dst.write = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL;
+ alu.src[0].sel = ctx->temp_reg;
+ alu.src[0].chan = 3;
+ alu.src[1].sel = src_gpr;
+ alu.src[1].chan = tgsi_chan(&inst->Src[0], 1);
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = 1;
+ alu.dst.write = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL;
+ alu.src[0].sel = ctx->temp_reg;
+ alu.src[0].chan = 3;
+ alu.src[1].sel = src_gpr;
+ alu.src[1].chan = tgsi_chan(&inst->Src[0], 2);
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = 2;
+ alu.dst.write = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV;
+ alu.src[0].sel = 249;
+ alu.src[0].chan = 0;
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = 3;
+ alu.last = 1;
+ alu.dst.write = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ src_gpr = ctx->temp_reg;
+
+ /* TODO use temp if src_gpr is not a temporary reg (File != TEMPORARY) */
+ memset(&tex, 0, sizeof(struct r600_bc_tex));
+ tex.inst = ctx->inst_info->r600_opcode;
+ tex.resource_id = ctx->file_offset[inst->Src[1].Register.File] + inst->Src[1].Register.Index;
+ tex.sampler_id = tex.resource_id;
+ tex.src_gpr = src_gpr;
+ tex.dst_gpr = ctx->file_offset[inst->Dst[0].Register.File] + inst->Dst[0].Register.Index;
+ tex.dst_sel_x = 0;
+ tex.dst_sel_y = 1;
+ tex.dst_sel_z = 2;
+ tex.dst_sel_w = 3;
+ tex.src_sel_x = 0;
+ tex.src_sel_y = 1;
+ tex.src_sel_z = 2;
+ tex.src_sel_w = 3;
+
+ if (inst->Texture.Texture != TGSI_TEXTURE_RECT) {
+ tex.coord_type_x = 1;
+ tex.coord_type_y = 1;
+ tex.coord_type_z = 1;
+ tex.coord_type_w = 1;
+ }
+ return r600_bc_add_tex(ctx->bc, &tex);
+}
+
+static int tgsi_lrp(struct r600_shader_ctx *ctx)
+{
+ struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+ struct r600_bc_alu_src r600_src[3];
+ struct r600_bc_alu alu;
+ unsigned i;
+ int r;
+
+ r = tgsi_split_constant(ctx, r600_src);
+ if (r)
+ return r;
+ /* 1 - src0 */
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD;
+ alu.src[0].sel = 249;
+ alu.src[0].chan = 0;
+ alu.src[1] = r600_src[0];
+ alu.src[1].chan = tgsi_chan(&inst->Src[0], i);
+ alu.src[1].neg = 1;
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = i;
+ if (i == 3) {
+ alu.last = 1;
+ }
+ alu.dst.write = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ r = r600_bc_add_literal(ctx->bc, ctx->value);
+ if (r)
+ return r;
+
+ /* (1 - src0) * src2 */
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL;
+ alu.src[0].sel = ctx->temp_reg;
+ alu.src[0].chan = i;
+ alu.src[1] = r600_src[2];
+ alu.src[1].chan = tgsi_chan(&inst->Src[2], i);
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = i;
+ if (i == 3) {
+ alu.last = 1;
+ }
+ alu.dst.write = 1;
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ r = r600_bc_add_literal(ctx->bc, ctx->value);
+ if (r)
+ return r;
+
+ /* src0 * src1 + (1 - src0) * src2 */
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bc_alu));
+ alu.inst = V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD;
+ alu.is_op3 = 1;
+ alu.src[0] = r600_src[0];
+ alu.src[0].chan = tgsi_chan(&inst->Src[0], i);
+ alu.src[1] = r600_src[1];
+ alu.src[1].chan = tgsi_chan(&inst->Src[1], i);
+ alu.src[2].sel = ctx->temp_reg;
+ alu.src[2].chan = i;
+ alu.dst.sel = ctx->temp_reg;
+ alu.dst.chan = i;
+ if (i == 3) {
+ alu.last = 1;
+ }
+ r = r600_bc_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ return tgsi_helper_copy(ctx, inst);
+}
+
+static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = {
+ {TGSI_OPCODE_ARL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_MOV, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV, tgsi_op2},
+ {TGSI_OPCODE_LIT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_lit},
+ {TGSI_OPCODE_RCP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE, tgsi_trans_srcx_replicate},
+ {TGSI_OPCODE_RSQ, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_IEEE, tgsi_trans_srcx_replicate},
+ {TGSI_OPCODE_EXP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_LOG, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_MUL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL, tgsi_op2},
+ {TGSI_OPCODE_ADD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD, tgsi_op2},
+ {TGSI_OPCODE_DP3, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, tgsi_dp},
+ {TGSI_OPCODE_DP4, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, tgsi_dp},
+ {TGSI_OPCODE_DST, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_MIN, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN, tgsi_op2},
+ {TGSI_OPCODE_MAX, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX, tgsi_op2},
+ {TGSI_OPCODE_SLT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT, tgsi_slt},
+ {TGSI_OPCODE_SGE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_MAD, 1, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD, tgsi_op3},
+ {TGSI_OPCODE_SUB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD, tgsi_op2},
+ {TGSI_OPCODE_LRP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_lrp},
+ {TGSI_OPCODE_CND, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ /* gap */
+ {20, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_DP2A, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ /* gap */
+ {22, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {23, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_FRC, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_CLAMP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_FLR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ROUND, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_EX2, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE, tgsi_trans_srcx_replicate},
+ {TGSI_OPCODE_LG2, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_POW, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_XPD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ /* gap */
+ {32, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ABS, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV, tgsi_op2},
+ {TGSI_OPCODE_RCC, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_DPH, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_COS, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_DDX, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_DDY, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_KILP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, /* predicated kill */
+ {TGSI_OPCODE_PK2H, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_PK2US, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_PK4B, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_PK4UB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_RFL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SEQ, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SFL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SGT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SIN, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SLE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SNE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_STR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_TEX, 0, 0x10, tgsi_tex},
+ {TGSI_OPCODE_TXD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_TXP, 0, 0x10, tgsi_tex},
+ {TGSI_OPCODE_UP2H, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_UP2US, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_UP4B, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_UP4UB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_X2D, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ARA, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ARR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_BRA, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_CAL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_RET, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SSG, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, /* SGN */
+ {TGSI_OPCODE_CMP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SCS, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_TXB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_NRM, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_DIV, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_DP2, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, tgsi_dp},
+ {TGSI_OPCODE_TXL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_BRK, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_IF, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ /* gap */
+ {75, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {76, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ELSE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ENDIF, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ /* gap */
+ {79, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {80, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_PUSHA, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_POPA, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_CEIL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_I2F, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_NOT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_TRUNC, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SHL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ /* gap */
+ {88, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_AND, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_OR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_MOD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_XOR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SAD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_TXF, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_TXQ, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_CONT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_EMIT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ENDPRIM, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_BGNLOOP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_BGNSUB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ENDLOOP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ENDSUB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ /* gap */
+ {103, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {104, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {105, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {106, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_NOP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ /* gap */
+ {108, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {109, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {110, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {111, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_NRM4, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_CALLNZ, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_IFC, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_BREAKC, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_KIL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT, tgsi_kill}, /* conditional kill */
+ {TGSI_OPCODE_END, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_end}, /* aka HALT */
+ /* gap */
+ {118, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_F2I, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_IDIV, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_IMAX, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_IMIN, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_INEG, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ISGE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ISHR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ISLT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_F2U, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_U2F, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_UADD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_UDIV, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_UMAD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_UMAX, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_UMIN, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_UMOD, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_UMUL, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_USEQ, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_USGE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_USHR, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_USLT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_USNE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_SWITCH, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_CASE, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_DEFAULT, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_ENDSWITCH, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_LAST, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+};
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index 40064ba8a9..2ee7780ead 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -23,243 +23,25 @@
#ifndef R600_SHADER_H
#define R600_SHADER_H
-#include "r600_compiler.h"
-#include "radeon.h"
-
-struct r600_shader_operand {
- struct c_vector *vector;
- unsigned sel;
- unsigned chan;
- unsigned neg;
- unsigned abs;
-};
-
-struct r600_shader_vfetch {
- struct list_head head;
- unsigned cf_addr;
- struct r600_shader_operand src[2];
- struct r600_shader_operand dst[4];
-};
-
-struct r600_shader_inst {
- unsigned is_op3;
- unsigned opcode;
- unsigned inst;
- struct r600_shader_operand src[3];
- struct r600_shader_operand dst;
- unsigned last;
-};
-
-struct r600_shader_alu {
- struct list_head head;
- unsigned nalu;
- unsigned nliteral;
- unsigned nconstant;
- struct r600_shader_inst alu[5];
- u32 literal[4];
-};
-
-struct r600_shader_node {
- struct list_head head;
- unsigned cf_id; /**< cf index (in dw) in byte code */
- unsigned cf_addr; /**< instructions index (in dw) in byte code */
- unsigned nslot; /**< number of slot (2 dw) needed by this node */
- unsigned nfetch;
- struct c_node *node; /**< compiler node from which this node originate */
- struct list_head vfetch; /**< list of vfetch instructions */
- struct list_head alu; /**< list of alu instructions */
-};
+#include "r600_asm.h"
struct r600_shader_io {
- unsigned name;
- unsigned gpr;
- int sid;
+ unsigned name;
+ unsigned gpr;
+ unsigned done;
+ int sid;
+ unsigned interpolate;
};
struct r600_shader {
- unsigned stack_size; /**< stack size needed by this shader */
- unsigned ngpr; /**< number of GPR needed by this shader */
- unsigned nconstant; /**< number of constants used by this shader */
- unsigned nresource; /**< number of resources used by this shader */
- unsigned noutput;
- unsigned ninput;
- unsigned nvector;
- unsigned ncf; /**< total number of cf clauses */
- unsigned nslot; /**< total number of slots (2 dw) */
- unsigned flat_shade; /**< are we flat shading */
- struct list_head nodes; /**< list of node */
- struct r600_shader_io input[32];
- struct r600_shader_io output[32];
- /* TODO replace GPR by some better register allocator */
- struct c_vector **gpr;
- unsigned ndw; /**< bytes code size in dw */
- u32 *bcode; /**< bytes code */
- enum pipe_format resource_format[160]; /**< format of resource */
- struct c_shader cshader;
- boolean r6xx_compile;
+ unsigned processor_type;
+ struct r600_bc bc;
+ boolean flat_shade;
+ unsigned ninput;
+ unsigned noutput;
+ struct r600_shader_io input[32];
+ struct r600_shader_io output[32];
+ enum radeon_family family;
};
-void r600_shader_cleanup(struct r600_shader *rshader);
-int r600_shader_register(struct r600_shader *rshader);
-int r600_shader_node(struct r600_shader *shader);
-void r600_shader_node_place(struct r600_shader *rshader);
-int r600_shader_find_gpr(struct r600_shader *rshader, struct c_vector *v, unsigned swizzle,
- struct r600_shader_operand *operand);
-int r600_shader_vfetch_bytecode(struct r600_shader *rshader,
- struct r600_shader_node *rnode,
- struct r600_shader_vfetch *vfetch,
- unsigned *cid);
-int r600_shader_update(struct r600_shader *rshader,
- enum pipe_format *resource_format);
-int r600_shader_legalize(struct r600_shader *rshader);
-int r600_cshader_legalize(struct c_shader *shader);
-
-int r700_shader_translate(struct r600_shader *rshader);
-
-int c_shader_from_tgsi(struct c_shader *shader, unsigned type,
- const struct tgsi_token *tokens);
-int r600_shader_register(struct r600_shader *rshader);
-int r600_shader_translate_rec(struct r600_shader *rshader, struct c_node *node);
-int r700_shader_translate(struct r600_shader *rshader);
-int r600_shader_insert_fetch(struct c_shader *shader);
-
-int r6xx_shader_alu_translate(struct r600_shader *rshader,
- struct r600_shader_node *rnode,
- unsigned *cid);
-
-enum r600_instruction {
- INST_ADD = 0,
- INST_MUL = 1,
- INST_MUL_IEEE = 2,
- INST_MAX = 3,
- INST_MIN = 4,
- INST_MAX_DX10 = 5,
- INST_MIN_DX10 = 6,
- INST_SETE = 7,
- INST_SETGT = 8,
- INST_SETGE = 9,
- INST_SETNE = 10,
- INST_SETE_DX10 = 11,
- INST_SETGT_DX10 = 12,
- INST_SETGE_DX10 = 13,
- INST_SETNE_DX10 = 14,
- INST_FRACT = 15,
- INST_TRUNC = 16,
- INST_CEIL = 17,
- INST_RNDNE = 18,
- INST_FLOOR = 19,
- INST_MOVA = 20,
- INST_MOVA_FLOOR = 21,
- INST_MOVA_INT = 22,
- INST_MOV = 23,
- INST_NOP = 24,
- INST_PRED_SETGT_UINT = 25,
- INST_PRED_SETGE_UINT = 26,
- INST_PRED_SETE = 27,
- INST_PRED_SETGT = 28,
- INST_PRED_SETGE = 29,
- INST_PRED_SETNE = 30,
- INST_PRED_SET_INV = 31,
- INST_PRED_SET_POP = 32,
- INST_PRED_SET_CLR = 33,
- INST_PRED_SET_RESTORE = 34,
- INST_PRED_SETE_PUSH = 35,
- INST_PRED_SETGT_PUSH = 36,
- INST_PRED_SETGE_PUSH = 37,
- INST_PRED_SETNE_PUSH = 38,
- INST_KILLE = 39,
- INST_KILLGT = 40,
- INST_KILLGE = 41,
- INST_KILLNE = 42,
- INST_AND_INT = 43,
- INST_OR_INT = 44,
- INST_XOR_INT = 45,
- INST_NOT_INT = 46,
- INST_ADD_INT = 47,
- INST_SUB_INT = 48,
- INST_MAX_INT = 49,
- INST_MIN_INT = 50,
- INST_MAX_UINT = 51,
- INST_MIN_UINT = 52,
- INST_SETE_INT = 53,
- INST_SETGT_INT = 54,
- INST_SETGE_INT = 55,
- INST_SETNE_INT = 56,
- INST_SETGT_UINT = 57,
- INST_SETGE_UINT = 58,
- INST_KILLGT_UINT = 59,
- INST_KILLGE_UINT = 60,
- INST_PRED_SETE_INT = 61,
- INST_PRED_SETGT_INT = 62,
- INST_PRED_SETGE_INT = 63,
- INST_PRED_SETNE_INT = 64,
- INST_KILLE_INT = 65,
- INST_KILLGT_INT = 66,
- INST_KILLGE_INT = 67,
- INST_KILLNE_INT = 68,
- INST_PRED_SETE_PUSH_INT = 69,
- INST_PRED_SETGT_PUSH_INT = 70,
- INST_PRED_SETGE_PUSH_INT = 71,
- INST_PRED_SETNE_PUSH_INT = 72,
- INST_PRED_SETLT_PUSH_INT = 73,
- INST_PRED_SETLE_PUSH_INT = 74,
- INST_DOT4 = 75,
- INST_DOT4_IEEE = 76,
- INST_CUBE = 77,
- INST_MAX4 = 78,
- INST_MOVA_GPR_INT = 79,
- INST_EXP_IEEE = 80,
- INST_LOG_CLAMPED = 81,
- INST_LOG_IEEE = 82,
- INST_RECIP_CLAMPED = 83,
- INST_RECIP_FF = 84,
- INST_RECIP_IEEE = 85,
- INST_RECIPSQRT_CLAMPED = 86,
- INST_RECIPSQRT_FF = 87,
- INST_RECIPSQRT_IEEE = 88,
- INST_SQRT_IEEE = 89,
- INST_FLT_TO_INT = 90,
- INST_INT_TO_FLT = 91,
- INST_UINT_TO_FLT = 92,
- INST_SIN = 93,
- INST_COS = 94,
- INST_ASHR_INT = 95,
- INST_LSHR_INT = 96,
- INST_LSHL_INT = 97,
- INST_MULLO_INT = 98,
- INST_MULHI_INT = 99,
- INST_MULLO_UINT = 100,
- INST_MULHI_UINT = 101,
- INST_RECIP_INT = 102,
- INST_RECIP_UINT = 103,
- INST_FLT_TO_UINT = 104,
- INST_MUL_LIT = 105,
- INST_MUL_LIT_M2 = 106,
- INST_MUL_LIT_M4 = 107,
- INST_MUL_LIT_D2 = 108,
- INST_MULADD = 109,
- INST_MULADD_M2 = 110,
- INST_MULADD_M4 = 111,
- INST_MULADD_D2 = 112,
- INST_MULADD_IEEE = 113,
- INST_MULADD_IEEE_M2 = 114,
- INST_MULADD_IEEE_M4 = 115,
- INST_MULADD_IEEE_D2 = 116,
- INST_CNDE = 117,
- INST_CNDGT = 118,
- INST_CNDGE = 119,
- INST_CNDE_INT = 120,
- INST_CNDGT_INT = 121,
- INST_CNDGE_INT = 122,
- INST_COUNT
-};
-
-struct r600_instruction_info {
- enum r600_instruction instruction;
- unsigned opcode;
- unsigned is_trans;
- unsigned is_op3;
-};
-
-
#endif
diff --git a/src/gallium/drivers/r600/r600_sq.h b/src/gallium/drivers/r600/r600_sq.h
index 447ba98f00..002660c654 100644
--- a/src/gallium/drivers/r600/r600_sq.h
+++ b/src/gallium/drivers/r600/r600_sq.h
@@ -87,9 +87,9 @@
#define G_SQ_CF_WORD1_BARRIER(x) (((x) >> 31) & 0x1)
#define C_SQ_CF_WORD1_BARRIER 0x7FFFFFFF
#define P_SQ_CF_ALU_WORD0
-#define S_SQ_CF_ALU_WORD0_ALU_ADDR(x) (((x) & 0x3FFFFF) << 0)
-#define G_SQ_CF_ALU_WORD0_ALU_ADDR(x) (((x) >> 0) & 0x3FFFFF)
-#define C_SQ_CF_ALU_WORD0_ALU_ADDR 0xFFC00000
+#define S_SQ_CF_ALU_WORD0_ADDR(x) (((x) & 0x3FFFFF) << 0)
+#define G_SQ_CF_ALU_WORD0_ADDR(x) (((x) >> 0) & 0x3FFFFF)
+#define C_SQ_CF_ALU_WORD0_ADDR 0xFFC00000
#define S_SQ_CF_ALU_WORD0_KCACHE_BANK0(x) (((x) & 0xF) << 22)
#define G_SQ_CF_ALU_WORD0_KCACHE_BANK0(x) (((x) >> 22) & 0xF)
#define C_SQ_CF_ALU_WORD0_KCACHE_BANK0 0xFC3FFFFF
@@ -109,15 +109,15 @@
#define S_SQ_CF_ALU_WORD1_KCACHE_ADDR1(x) (((x) & 0xFF) << 10)
#define G_SQ_CF_ALU_WORD1_KCACHE_ADDR1(x) (((x) >> 10) & 0xFF)
#define C_SQ_CF_ALU_WORD1_KCACHE_ADDR1 0xFFFC03FF
-#define S_SQ_CF_ALU_WORD1_ALU_COUNT(x) (((x) & 0x7F) << 18)
-#define G_SQ_CF_ALU_WORD1_ALU_COUNT(x) (((x) >> 18) & 0x7F)
-#define C_SQ_CF_ALU_WORD1_ALU_COUNT 0xFE03FFFF
+#define S_SQ_CF_ALU_WORD1_COUNT(x) (((x) & 0x7F) << 18)
+#define G_SQ_CF_ALU_WORD1_COUNT(x) (((x) >> 18) & 0x7F)
+#define C_SQ_CF_ALU_WORD1_COUNT 0xFE03FFFF
#define S_SQ_CF_ALU_WORD1_USES_WATERFALL(x) (((x) & 0x1) << 25)
#define G_SQ_CF_ALU_WORD1_USES_WATERFALL(x) (((x) >> 25) & 0x1)
#define C_SQ_CF_ALU_WORD1_USES_WATERFALL 0xFDFFFFFF
-#define S_SQ_CF_ALU_WORD1_CF_ALU_INST(x) (((x) & 0xF) << 26)
-#define G_SQ_CF_ALU_WORD1_CF_ALU_INST(x) (((x) >> 26) & 0xF)
-#define C_SQ_CF_ALU_WORD1_CF_ALU_INST 0xC3FFFFFF
+#define S_SQ_CF_ALU_WORD1_CF_INST(x) (((x) & 0xF) << 26)
+#define G_SQ_CF_ALU_WORD1_CF_INST(x) (((x) >> 26) & 0xF)
+#define C_SQ_CF_ALU_WORD1_CF_INST 0xC3FFFFFF
#define V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU 0x00000008
#define V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE 0x00000009
#define V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER 0x0000000A
@@ -546,6 +546,8 @@
#define S_SQ_TEX_WORD1_COORD_TYPE_X(x) (((x) & 0x1) << 28)
#define G_SQ_TEX_WORD1_COORD_TYPE_X(x) (((x) >> 28) & 0x1)
#define C_SQ_TEX_WORD1_COORD_TYPE_X 0xEFFFFFFF
+#define V_SQ_TEX_WORD1_COORD_UNNORMALIZED 0x00000000
+#define V_SQ_TEX_WORD1_COORD_NORMALIZED 0x00000001
#define S_SQ_TEX_WORD1_COORD_TYPE_Y(x) (((x) & 0x1) << 29)
#define G_SQ_TEX_WORD1_COORD_TYPE_Y(x) (((x) >> 29) & 0x1)
#define C_SQ_TEX_WORD1_COORD_TYPE_Y 0xDFFFFFFF
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index 4150f88785..3efd409ae0 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -24,36 +24,605 @@
* Jerome Glisse
*/
#include <stdio.h>
-#include <util/u_inlines.h>
-#include <util/u_format.h>
-#include <util/u_memory.h>
+#include <errno.h>
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "util/u_memory.h"
#include "r600_screen.h"
-#include "r600_texture.h"
#include "r600_context.h"
+#include "r600_resource.h"
#include "r600d.h"
+#include "r600_state_inlines.h"
+static void *r600_create_blend_state(struct pipe_context *ctx,
+ const struct pipe_blend_state *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+
+ return r600_context_state(rctx, pipe_blend_type, state);
+}
+
+static void *r600_create_dsa_state(struct pipe_context *ctx,
+ const struct pipe_depth_stencil_alpha_state *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+
+ return r600_context_state(rctx, pipe_dsa_type, state);
+}
+
+static void *r600_create_rs_state(struct pipe_context *ctx,
+ const struct pipe_rasterizer_state *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+
+ return r600_context_state(rctx, pipe_rasterizer_type, state);
+}
+
+static void *r600_create_sampler_state(struct pipe_context *ctx,
+ const struct pipe_sampler_state *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+
+ return r600_context_state(rctx, pipe_sampler_type, state);
+}
+
+static void r600_sampler_view_destroy(struct pipe_context *ctx,
+ struct pipe_sampler_view *state)
+{
+ struct r600_context_state *rstate = (struct r600_context_state *)state;
+
+ r600_context_state_decref(rstate);
+}
+
+static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *ctx,
+ struct pipe_resource *texture,
+ const struct pipe_sampler_view *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate;
+
+ rstate = r600_context_state(rctx, pipe_sampler_type, state);
+ pipe_reference(NULL, &texture->reference);
+ rstate->state.sampler_view.texture = texture;
+ rstate->state.sampler_view.reference.count = 1;
+ rstate->state.sampler_view.context = ctx;
+ return &rstate->state.sampler_view;
+}
+
+static void *r600_create_shader_state(struct pipe_context *ctx,
+ const struct pipe_shader_state *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+
+ return r600_context_state(rctx, pipe_shader_type, state);
+}
+
+static void *r600_create_vertex_elements(struct pipe_context *ctx,
+ unsigned count,
+ const struct pipe_vertex_element *elements)
+{
+ struct r600_vertex_element *v = CALLOC_STRUCT(r600_vertex_element);
+
+ assert(count < 32);
+ v->count = count;
+ memcpy(v->elements, elements, count * sizeof(struct pipe_vertex_element));
+ v->refcount = 1;
+ return v;
+}
+
+static void r600_bind_state(struct pipe_context *ctx, void *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate = (struct r600_context_state *)state;
+
+ if (state == NULL)
+ return;
+ switch (rstate->type) {
+ case pipe_rasterizer_type:
+ rctx->rasterizer = r600_context_state_decref(rctx->rasterizer);
+ rctx->rasterizer = r600_context_state_incref(rstate);
+ break;
+ case pipe_poly_stipple_type:
+ rctx->poly_stipple = r600_context_state_decref(rctx->poly_stipple);
+ rctx->poly_stipple = r600_context_state_incref(rstate);
+ break;
+ case pipe_scissor_type:
+ rctx->scissor = r600_context_state_decref(rctx->scissor);
+ rctx->scissor = r600_context_state_incref(rstate);
+ break;
+ case pipe_clip_type:
+ rctx->clip = r600_context_state_decref(rctx->clip);
+ rctx->clip = r600_context_state_incref(rstate);
+ break;
+ case pipe_depth_type:
+ rctx->depth = r600_context_state_decref(rctx->depth);
+ rctx->depth = r600_context_state_incref(rstate);
+ break;
+ case pipe_stencil_type:
+ rctx->stencil = r600_context_state_decref(rctx->stencil);
+ rctx->stencil = r600_context_state_incref(rstate);
+ break;
+ case pipe_alpha_type:
+ rctx->alpha = r600_context_state_decref(rctx->alpha);
+ rctx->alpha = r600_context_state_incref(rstate);
+ break;
+ case pipe_dsa_type:
+ rctx->dsa = r600_context_state_decref(rctx->dsa);
+ rctx->dsa = r600_context_state_incref(rstate);
+ break;
+ case pipe_blend_type:
+ rctx->blend = r600_context_state_decref(rctx->blend);
+ rctx->blend = r600_context_state_incref(rstate);
+ break;
+ case pipe_framebuffer_type:
+ rctx->framebuffer = r600_context_state_decref(rctx->framebuffer);
+ rctx->framebuffer = r600_context_state_incref(rstate);
+ break;
+ case pipe_stencil_ref_type:
+ rctx->stencil_ref = r600_context_state_decref(rctx->stencil_ref);
+ rctx->stencil_ref = r600_context_state_incref(rstate);
+ break;
+ case pipe_viewport_type:
+ rctx->viewport = r600_context_state_decref(rctx->viewport);
+ rctx->viewport = r600_context_state_incref(rstate);
+ break;
+ case pipe_shader_type:
+ case pipe_sampler_type:
+ case pipe_sampler_view_type:
+ default:
+ R600_ERR("invalid type %d\n", rstate->type);
+ return;
+ }
+}
+
+static void r600_bind_ps_shader(struct pipe_context *ctx, void *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate = (struct r600_context_state *)state;
+
+ rctx->ps_shader = r600_context_state_decref(rctx->ps_shader);
+ rctx->ps_shader = r600_context_state_incref(rstate);
+}
+
+static void r600_bind_vs_shader(struct pipe_context *ctx, void *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate = (struct r600_context_state *)state;
+
+ rctx->vs_shader = r600_context_state_decref(rctx->vs_shader);
+ rctx->vs_shader = r600_context_state_incref(rstate);
+}
+
+static void r600_delete_vertex_element(struct pipe_context *ctx, void *state)
+{
+ struct r600_vertex_element *v = (struct r600_vertex_element*)state;
+
+ if (v == NULL)
+ return;
+ if (--v->refcount)
+ return;
+ free(v);
+}
+
+static void r600_bind_vertex_elements(struct pipe_context *ctx, void *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_vertex_element *v = (struct r600_vertex_element*)state;
+
+ r600_delete_vertex_element(ctx, rctx->vertex_elements);
+ rctx->vertex_elements = v;
+ if (v) {
+ v->refcount++;
+ }
+}
+
+static void r600_bind_ps_sampler(struct pipe_context *ctx,
+ unsigned count, void **states)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate;
+ unsigned i;
+
+ for (i = 0; i < rctx->ps_nsampler; i++) {
+ rctx->ps_sampler[i] = r600_context_state_decref(rctx->ps_sampler[i]);
+ }
+ for (i = 0; i < count; i++) {
+ rstate = (struct r600_context_state *)states[i];
+ rctx->ps_sampler[i] = r600_context_state_incref(rstate);
+ }
+ rctx->ps_nsampler = count;
+}
+
+static void r600_bind_vs_sampler(struct pipe_context *ctx,
+ unsigned count, void **states)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate;
+ unsigned i;
+
+ for (i = 0; i < rctx->vs_nsampler; i++) {
+ rctx->vs_sampler[i] = r600_context_state_decref(rctx->vs_sampler[i]);
+ }
+ for (i = 0; i < count; i++) {
+ rstate = (struct r600_context_state *)states[i];
+ rctx->vs_sampler[i] = r600_context_state_incref(rstate);
+ }
+ rctx->vs_nsampler = count;
+}
static void r600_delete_state(struct pipe_context *ctx, void *state)
{
- struct radeon_state *rstate = state;
+ struct r600_context_state *rstate = (struct r600_context_state *)state;
- radeon_state_decref(rstate);
+ r600_context_state_decref(rstate);
}
-static void *r600_create_blend_state(struct pipe_context *ctx,
- const struct pipe_blend_state *state)
+static void r600_set_blend_color(struct pipe_context *ctx,
+ const struct pipe_blend_color *color)
+{
+ struct r600_context *rctx = r600_context(ctx);
+
+ rctx->blend_color = *color;
+}
+
+static void r600_set_clip_state(struct pipe_context *ctx,
+ const struct pipe_clip_state *state)
+{
+}
+
+static void r600_set_constant_buffer(struct pipe_context *ctx,
+ uint shader, uint index,
+ struct pipe_resource *buffer)
{
struct r600_screen *rscreen = r600_screen(ctx->screen);
+ struct r600_context *rctx = r600_context(ctx);
+ unsigned nconstant = 0, i, type, id;
+ struct radeon_state *rstate;
+ struct pipe_transfer *transfer;
+ u32 *ptr;
+
+ switch (shader) {
+ case PIPE_SHADER_VERTEX:
+ id = R600_VS_CONSTANT;
+ type = R600_VS_CONSTANT_TYPE;
+ break;
+ case PIPE_SHADER_FRAGMENT:
+ id = R600_PS_CONSTANT;
+ type = R600_PS_CONSTANT_TYPE;
+ break;
+ default:
+ R600_ERR("unsupported %d\n", shader);
+ return;
+ }
+ if (buffer && buffer->width0 > 0) {
+ nconstant = buffer->width0 / 16;
+ ptr = pipe_buffer_map(ctx, buffer, PIPE_TRANSFER_READ, &transfer);
+ if (ptr == NULL)
+ return;
+ for (i = 0; i < nconstant; i++) {
+ rstate = radeon_state(rscreen->rw, type, id + i);
+ if (rstate == NULL)
+ return;
+ rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT0_0] = ptr[i * 4 + 0];
+ rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT1_0] = ptr[i * 4 + 1];
+ rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT2_0] = ptr[i * 4 + 2];
+ rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT3_0] = ptr[i * 4 + 3];
+ if (radeon_state_pm4(rstate))
+ return;
+ if (radeon_draw_set_new(rctx->draw, rstate))
+ return;
+ }
+ pipe_buffer_unmap(ctx, buffer, transfer);
+ }
+}
+
+static void r600_set_ps_sampler_view(struct pipe_context *ctx,
+ unsigned count,
+ struct pipe_sampler_view **views)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate;
+ unsigned i;
+
+ for (i = 0; i < rctx->ps_nsampler_view; i++) {
+ rctx->ps_sampler_view[i] = r600_context_state_decref(rctx->ps_sampler_view[i]);
+ }
+ for (i = 0; i < count; i++) {
+ rstate = (struct r600_context_state *)views[i];
+ rctx->ps_sampler_view[i] = r600_context_state_incref(rstate);
+ }
+ rctx->ps_nsampler_view = count;
+}
+
+static void r600_set_vs_sampler_view(struct pipe_context *ctx,
+ unsigned count,
+ struct pipe_sampler_view **views)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate;
+ unsigned i;
+
+ for (i = 0; i < rctx->vs_nsampler_view; i++) {
+ rctx->vs_sampler_view[i] = r600_context_state_decref(rctx->vs_sampler_view[i]);
+ }
+ for (i = 0; i < count; i++) {
+ rstate = (struct r600_context_state *)views[i];
+ rctx->vs_sampler_view[i] = r600_context_state_incref(rstate);
+ }
+ rctx->vs_nsampler_view = count;
+}
+
+static void r600_set_framebuffer_state(struct pipe_context *ctx,
+ const struct pipe_framebuffer_state *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate;
+
+ rstate = r600_context_state(rctx, pipe_framebuffer_type, state);
+ r600_bind_state(ctx, rstate);
+}
+
+static void r600_set_polygon_stipple(struct pipe_context *ctx,
+ const struct pipe_poly_stipple *state)
+{
+}
+
+static void r600_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
+{
+}
+
+static void r600_set_scissor_state(struct pipe_context *ctx,
+ const struct pipe_scissor_state *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate;
+
+ rstate = r600_context_state(rctx, pipe_scissor_type, state);
+ r600_bind_state(ctx, rstate);
+ /* refcount is taken care of this */
+ r600_delete_state(ctx, rstate);
+}
+
+static void r600_set_stencil_ref(struct pipe_context *ctx,
+ const struct pipe_stencil_ref *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate;
+
+ rstate = r600_context_state(rctx, pipe_stencil_ref_type, state);
+ r600_bind_state(ctx, rstate);
+ /* refcount is taken care of this */
+ r600_delete_state(ctx, rstate);
+}
+
+static void r600_set_vertex_buffers(struct pipe_context *ctx,
+ unsigned count,
+ const struct pipe_vertex_buffer *buffers)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ unsigned i;
+
+ for (i = 0; i < rctx->nvertex_buffer; i++) {
+ pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL);
+ }
+ memcpy(rctx->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count);
+ for (i = 0; i < count; i++) {
+ rctx->vertex_buffer[i].buffer = NULL;
+ pipe_resource_reference(&rctx->vertex_buffer[i].buffer, buffers[i].buffer);
+ }
+ rctx->nvertex_buffer = count;
+}
+
+static void r600_set_index_buffer(struct pipe_context *ctx,
+ const struct pipe_index_buffer *ib)
+{
+ struct r600_context *rctx = r600_context(ctx);
+
+ if (ib) {
+ pipe_resource_reference(&rctx->index_buffer.buffer, ib->buffer);
+ memcpy(&rctx->index_buffer, ib, sizeof(rctx->index_buffer));
+ } else {
+ pipe_resource_reference(&rctx->index_buffer.buffer, NULL);
+ memset(&rctx->index_buffer, 0, sizeof(rctx->index_buffer));
+ }
+
+ /* TODO make this more like a state */
+}
+
+static void r600_set_viewport_state(struct pipe_context *ctx,
+ const struct pipe_viewport_state *state)
+{
+ struct r600_context *rctx = r600_context(ctx);
+ struct r600_context_state *rstate;
+
+ rstate = r600_context_state(rctx, pipe_viewport_type, state);
+ r600_bind_state(ctx, rstate);
+ r600_delete_state(ctx, rstate);
+}
+
+void r600_init_state_functions(struct r600_context *rctx)
+{
+ rctx->context.create_blend_state = r600_create_blend_state;
+ rctx->context.create_depth_stencil_alpha_state = r600_create_dsa_state;
+ rctx->context.create_fs_state = r600_create_shader_state;
+ rctx->context.create_rasterizer_state = r600_create_rs_state;
+ rctx->context.create_sampler_state = r600_create_sampler_state;
+ rctx->context.create_sampler_view = r600_create_sampler_view;
+ rctx->context.create_vertex_elements_state = r600_create_vertex_elements;
+ rctx->context.create_vs_state = r600_create_shader_state;
+ rctx->context.bind_blend_state = r600_bind_state;
+ rctx->context.bind_depth_stencil_alpha_state = r600_bind_state;
+ rctx->context.bind_fragment_sampler_states = r600_bind_ps_sampler;
+ rctx->context.bind_fs_state = r600_bind_ps_shader;
+ rctx->context.bind_rasterizer_state = r600_bind_state;
+ rctx->context.bind_vertex_elements_state = r600_bind_vertex_elements;
+ rctx->context.bind_vertex_sampler_states = r600_bind_vs_sampler;
+ rctx->context.bind_vs_state = r600_bind_vs_shader;
+ rctx->context.delete_blend_state = r600_delete_state;
+ rctx->context.delete_depth_stencil_alpha_state = r600_delete_state;
+ rctx->context.delete_fs_state = r600_delete_state;
+ rctx->context.delete_rasterizer_state = r600_delete_state;
+ rctx->context.delete_sampler_state = r600_delete_state;
+ rctx->context.delete_vertex_elements_state = r600_delete_vertex_element;
+ rctx->context.delete_vs_state = r600_delete_state;
+ rctx->context.set_blend_color = r600_set_blend_color;
+ rctx->context.set_clip_state = r600_set_clip_state;
+ rctx->context.set_constant_buffer = r600_set_constant_buffer;
+ rctx->context.set_fragment_sampler_views = r600_set_ps_sampler_view;
+ rctx->context.set_framebuffer_state = r600_set_framebuffer_state;
+ rctx->context.set_polygon_stipple = r600_set_polygon_stipple;
+ rctx->context.set_sample_mask = r600_set_sample_mask;
+ rctx->context.set_scissor_state = r600_set_scissor_state;
+ rctx->context.set_stencil_ref = r600_set_stencil_ref;
+ rctx->context.set_vertex_buffers = r600_set_vertex_buffers;
+ rctx->context.set_index_buffer = r600_set_index_buffer;
+ rctx->context.set_vertex_sampler_views = r600_set_vs_sampler_view;
+ rctx->context.set_viewport_state = r600_set_viewport_state;
+ rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
+}
+
+struct r600_context_state *r600_context_state_incref(struct r600_context_state *rstate)
+{
+ if (rstate == NULL)
+ return NULL;
+ rstate->refcount++;
+ return rstate;
+}
+
+struct r600_context_state *r600_context_state_decref(struct r600_context_state *rstate)
+{
+ unsigned i;
+
+ if (rstate == NULL)
+ return NULL;
+ if (--rstate->refcount)
+ return NULL;
+ switch (rstate->type) {
+ case pipe_sampler_view_type:
+ pipe_resource_reference(&rstate->state.sampler_view.texture, NULL);
+ break;
+ case pipe_framebuffer_type:
+ for (i = 0; i < rstate->state.framebuffer.nr_cbufs; i++) {
+ pipe_surface_reference(&rstate->state.framebuffer.cbufs[i], NULL);
+ }
+ pipe_surface_reference(&rstate->state.framebuffer.zsbuf, NULL);
+ break;
+ case pipe_viewport_type:
+ case pipe_depth_type:
+ case pipe_rasterizer_type:
+ case pipe_poly_stipple_type:
+ case pipe_scissor_type:
+ case pipe_clip_type:
+ case pipe_stencil_type:
+ case pipe_alpha_type:
+ case pipe_dsa_type:
+ case pipe_blend_type:
+ case pipe_stencil_ref_type:
+ case pipe_shader_type:
+ case pipe_sampler_type:
+ break;
+ default:
+ R600_ERR("invalid type %d\n", rstate->type);
+ return NULL;
+ }
+ radeon_state_decref(rstate->rstate);
+ FREE(rstate);
+ return NULL;
+}
+
+struct r600_context_state *r600_context_state(struct r600_context *rctx, unsigned type, const void *state)
+{
+ struct r600_context_state *rstate = CALLOC_STRUCT(r600_context_state);
+ const union pipe_states *states = state;
+ unsigned i;
+ int r;
+
+ if (rstate == NULL)
+ return NULL;
+ rstate->type = type;
+ rstate->refcount = 1;
+
+ switch (rstate->type) {
+ case pipe_sampler_view_type:
+ rstate->state.sampler_view = (*states).sampler_view;
+ rstate->state.sampler_view.texture = NULL;
+ break;
+ case pipe_framebuffer_type:
+ rstate->state.framebuffer = (*states).framebuffer;
+ for (i = 0; i < rstate->state.framebuffer.nr_cbufs; i++) {
+ pipe_surface_reference(&rstate->state.framebuffer.cbufs[i],
+ (*states).framebuffer.cbufs[i]);
+ }
+ pipe_surface_reference(&rstate->state.framebuffer.zsbuf,
+ (*states).framebuffer.zsbuf);
+ break;
+ case pipe_viewport_type:
+ rstate->state.viewport = (*states).viewport;
+ break;
+ case pipe_depth_type:
+ rstate->state.depth = (*states).depth;
+ break;
+ case pipe_rasterizer_type:
+ rstate->state.rasterizer = (*states).rasterizer;
+ break;
+ case pipe_poly_stipple_type:
+ rstate->state.poly_stipple = (*states).poly_stipple;
+ break;
+ case pipe_scissor_type:
+ rstate->state.scissor = (*states).scissor;
+ break;
+ case pipe_clip_type:
+ rstate->state.clip = (*states).clip;
+ break;
+ case pipe_stencil_type:
+ rstate->state.stencil = (*states).stencil;
+ break;
+ case pipe_alpha_type:
+ rstate->state.alpha = (*states).alpha;
+ break;
+ case pipe_dsa_type:
+ rstate->state.dsa = (*states).dsa;
+ break;
+ case pipe_blend_type:
+ rstate->state.blend = (*states).blend;
+ break;
+ case pipe_stencil_ref_type:
+ rstate->state.stencil_ref = (*states).stencil_ref;
+ break;
+ case pipe_shader_type:
+ rstate->state.shader = (*states).shader;
+ r = r600_pipe_shader_create(&rctx->context, rstate, rstate->state.shader.tokens);
+ if (r) {
+ r600_context_state_decref(rstate);
+ return NULL;
+ }
+ break;
+ case pipe_sampler_type:
+ rstate->state.sampler = (*states).sampler;
+ break;
+ default:
+ R600_ERR("invalid type %d\n", rstate->type);
+ FREE(rstate);
+ return NULL;
+ }
+ return rstate;
+}
+
+static struct radeon_state *r600_blend(struct r600_context *rctx)
+{
+ struct r600_screen *rscreen = rctx->screen;
struct radeon_state *rstate;
+ const struct pipe_blend_state *state = &rctx->blend->state.blend;
+ int i;
rstate = radeon_state(rscreen->rw, R600_BLEND_TYPE, R600_BLEND);
if (rstate == NULL)
return NULL;
- rstate->states[R600_BLEND__CB_BLEND_RED] = 0x00000000;
- rstate->states[R600_BLEND__CB_BLEND_GREEN] = 0x00000000;
- rstate->states[R600_BLEND__CB_BLEND_BLUE] = 0x00000000;
- rstate->states[R600_BLEND__CB_BLEND_ALPHA] = 0x00000000;
- rstate->states[R600_BLEND__CB_BLEND0_CONTROL] = 0x00010001;
+ rstate->states[R600_BLEND__CB_BLEND_RED] = fui(rctx->blend_color.color[0]);
+ rstate->states[R600_BLEND__CB_BLEND_GREEN] = fui(rctx->blend_color.color[1]);
+ rstate->states[R600_BLEND__CB_BLEND_BLUE] = fui(rctx->blend_color.color[2]);
+ rstate->states[R600_BLEND__CB_BLEND_ALPHA] = fui(rctx->blend_color.color[3]);
+ rstate->states[R600_BLEND__CB_BLEND0_CONTROL] = 0x00000000;
rstate->states[R600_BLEND__CB_BLEND1_CONTROL] = 0x00000000;
rstate->states[R600_BLEND__CB_BLEND2_CONTROL] = 0x00000000;
rstate->states[R600_BLEND__CB_BLEND3_CONTROL] = 0x00000000;
@@ -62,6 +631,36 @@ static void *r600_create_blend_state(struct pipe_context *ctx,
rstate->states[R600_BLEND__CB_BLEND6_CONTROL] = 0x00000000;
rstate->states[R600_BLEND__CB_BLEND7_CONTROL] = 0x00000000;
rstate->states[R600_BLEND__CB_BLEND_CONTROL] = 0x00000000;
+
+ for (i = 0; i < 8; i++) {
+ unsigned eqRGB = state->rt[i].rgb_func;
+ unsigned srcRGB = state->rt[i].rgb_src_factor;
+ unsigned dstRGB = state->rt[i].rgb_dst_factor;
+
+ unsigned eqA = state->rt[i].alpha_func;
+ unsigned srcA = state->rt[i].alpha_src_factor;
+ unsigned dstA = state->rt[i].alpha_dst_factor;
+ uint32_t bc = 0;
+
+ if (!state->rt[i].blend_enable)
+ continue;
+
+ bc |= S_028804_COLOR_COMB_FCN(r600_translate_blend_function(eqRGB));
+ bc |= S_028804_COLOR_SRCBLEND(r600_translate_blend_factor(srcRGB));
+ bc |= S_028804_COLOR_DESTBLEND(r600_translate_blend_factor(dstRGB));
+
+ if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) {
+ bc |= S_028804_SEPARATE_ALPHA_BLEND(1);
+ bc |= S_028804_ALPHA_COMB_FCN(r600_translate_blend_function(eqA));
+ bc |= S_028804_ALPHA_SRCBLEND(r600_translate_blend_factor(srcA));
+ bc |= S_028804_ALPHA_DESTBLEND(r600_translate_blend_factor(dstA));
+ }
+
+ rstate->states[R600_BLEND__CB_BLEND0_CONTROL + i] = bc;
+ if (i == 0)
+ rstate->states[R600_BLEND__CB_BLEND_CONTROL] = bc;
+ }
+
if (radeon_state_pm4(rstate)) {
radeon_state_decref(rstate);
return NULL;
@@ -69,38 +668,24 @@ static void *r600_create_blend_state(struct pipe_context *ctx,
return rstate;
}
-static void r600_bind_blend_state(struct pipe_context *ctx, void *state)
-{
- struct r600_context *rctx = r600_context(ctx);
- radeon_draw_set(rctx->draw, state);
-}
-
-static void r600_set_blend_color(struct pipe_context *ctx,
- const struct pipe_blend_color *color)
+static struct radeon_state *r600_cb(struct r600_context *rctx, int cb)
{
-}
-
-static void r600_set_clip_state(struct pipe_context *ctx,
- const struct pipe_clip_state *state)
-{
-}
-
-static void r600_set_framebuffer_state(struct pipe_context *ctx,
- const struct pipe_framebuffer_state *state)
-{
- struct r600_screen *rscreen = r600_screen(ctx->screen);
- struct r600_context *rctx = r600_context(ctx);
- struct r600_texture *rtex;
- struct r600_buffer *rbuffer;
+ struct r600_screen *rscreen = rctx->screen;
+ struct r600_resource_texture *rtex;
+ struct r600_resource *rbuffer;
struct radeon_state *rstate;
- unsigned level = state->cbufs[0]->level;
+ const struct pipe_framebuffer_state *state = &rctx->framebuffer->state.framebuffer;
+ unsigned level = state->cbufs[cb]->level;
unsigned pitch, slice;
+ unsigned color_info;
+ unsigned format, swap, ntype;
+ const struct util_format_description *desc;
- rstate = radeon_state(rscreen->rw, R600_CB0_TYPE, R600_CB0);
+ rstate = radeon_state(rscreen->rw, R600_CB0_TYPE + cb, R600_CB0 + cb);
if (rstate == NULL)
- return;
- rtex = (struct r600_texture*)state->cbufs[0]->texture;
- rbuffer = (struct r600_buffer*)rtex->buffer;
+ return NULL;
+ rtex = (struct r600_resource_texture*)state->cbufs[cb]->texture;
+ rbuffer = &rtex->resource;
rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
rstate->bo[1] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
rstate->bo[2] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
@@ -108,10 +693,25 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx,
rstate->placement[2] = RADEON_GEM_DOMAIN_GTT;
rstate->placement[4] = RADEON_GEM_DOMAIN_GTT;
rstate->nbo = 3;
- pitch = rtex->pitch[level] / 8 - 1;
- slice = rtex->pitch[level] * state->cbufs[0]->height / 64 - 1;
+ pitch = (rtex->pitch[level] / rtex->bpt) / 8 - 1;
+ slice = (rtex->pitch[level] / rtex->bpt) * state->cbufs[cb]->height / 64 - 1;
+
+ ntype = 0;
+ desc = util_format_description(rtex->resource.base.b.format);
+ if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
+ ntype = V_0280A0_NUMBER_SRGB;
+
+ format = r600_translate_colorformat(rtex->resource.base.b.format);
+ swap = r600_translate_colorswap(rtex->resource.base.b.format);
+
+ color_info = S_0280A0_FORMAT(format) |
+ S_0280A0_COMP_SWAP(swap) |
+ S_0280A0_BLEND_CLAMP(1) |
+ S_0280A0_SOURCE_FORMAT(1) |
+ S_0280A0_NUMBER_TYPE(ntype);
+
rstate->states[R600_CB0__CB_COLOR0_BASE] = 0x00000000;
- rstate->states[R600_CB0__CB_COLOR0_INFO] = 0x08110068;
+ rstate->states[R600_CB0__CB_COLOR0_INFO] = color_info;
rstate->states[R600_CB0__CB_COLOR0_SIZE] = S_028060_PITCH_TILE_MAX(pitch) |
S_028060_SLICE_TILE_MAX(slice);
rstate->states[R600_CB0__CB_COLOR0_VIEW] = 0x00000000;
@@ -120,83 +720,124 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx,
rstate->states[R600_CB0__CB_COLOR0_MASK] = 0x00000000;
if (radeon_state_pm4(rstate)) {
radeon_state_decref(rstate);
- return;
+ return NULL;
}
- radeon_draw_set_new(rctx->draw, rstate);
- rctx->db = radeon_state_decref(rctx->db);
- if(state->zsbuf) {
- rtex = (struct r600_texture*)state->zsbuf->texture;
- rbuffer = (struct r600_buffer*)rtex->buffer;
- rctx->db = radeon_state(rscreen->rw, R600_DB_TYPE, R600_DB);
- if(rctx->db == NULL)
- return;
- rctx->db->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
- rctx->db->nbo = 1;
- rctx->db->placement[0] = RADEON_GEM_DOMAIN_VRAM;
- level = state->zsbuf->level;
- pitch = rtex->pitch[level] / 8 - 1;
- slice = rtex->pitch[level] * state->zsbuf->height / 64 - 1;
-
- rctx->db->states[R600_DB__DB_DEPTH_BASE] = 0x00000000;
- rctx->db->states[R600_DB__DB_DEPTH_INFO] = 0x00010006;
- rctx->db->states[R600_DB__DB_DEPTH_VIEW] = 0x00000000;
- rctx->db->states[R600_DB__DB_PREFETCH_LIMIT] = (state->zsbuf->height / 8) -1;
- rctx->db->states[R600_DB__DB_DEPTH_SIZE] = S_028000_PITCH_TILE_MAX(pitch) |
- S_028000_SLICE_TILE_MAX(slice);
- } else
- rctx->db = NULL;
- rctx->fb_state = *state;
-}
-
-static void *r600_create_fs_state(struct pipe_context *ctx,
- const struct pipe_shader_state *shader)
-{
- return r600_pipe_shader_create(ctx, C_PROGRAM_TYPE_FS, shader->tokens);
-}
-
-static void r600_bind_fs_state(struct pipe_context *ctx, void *state)
-{
- struct r600_context *rctx = r600_context(ctx);
-
- rctx->ps_shader = state;
+ return rstate;
}
-static void *r600_create_vs_state(struct pipe_context *ctx,
- const struct pipe_shader_state *shader)
+static struct radeon_state *r600_db(struct r600_context *rctx)
{
- return r600_pipe_shader_create(ctx, C_PROGRAM_TYPE_VS, shader->tokens);
-}
+ struct r600_screen *rscreen = rctx->screen;
+ struct r600_resource_texture *rtex;
+ struct r600_resource *rbuffer;
+ struct radeon_state *rstate;
+ const struct pipe_framebuffer_state *state = &rctx->framebuffer->state.framebuffer;
+ unsigned level;
+ unsigned pitch, slice, format;
-static void r600_bind_vs_state(struct pipe_context *ctx, void *state)
-{
- struct r600_context *rctx = r600_context(ctx);
+ if (state->zsbuf == NULL)
+ return NULL;
- rctx->vs_shader = state;
-}
+ rstate = radeon_state(rscreen->rw, R600_DB_TYPE, R600_DB);
+ if (rstate == NULL)
+ return NULL;
-static void r600_set_polygon_stipple(struct pipe_context *ctx,
- const struct pipe_poly_stipple *state)
-{
+ rtex = (struct r600_resource_texture*)state->zsbuf->texture;
+ rbuffer = &rtex->resource;
+ rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
+ rstate->nbo = 1;
+ rstate->placement[0] = RADEON_GEM_DOMAIN_VRAM;
+ level = state->zsbuf->level;
+ pitch = (rtex->pitch[level] / rtex->bpt) / 8 - 1;
+ slice = (rtex->pitch[level] / rtex->bpt) * state->zsbuf->height / 64 - 1;
+ format = r600_translate_dbformat(state->zsbuf->texture->format);
+ rstate->states[R600_DB__DB_DEPTH_BASE] = 0x00000000;
+ rstate->states[R600_DB__DB_DEPTH_INFO] = 0x00010000 |
+ S_028010_FORMAT(format);
+ rstate->states[R600_DB__DB_DEPTH_VIEW] = 0x00000000;
+ rstate->states[R600_DB__DB_PREFETCH_LIMIT] = (state->zsbuf->height / 8) -1;
+ rstate->states[R600_DB__DB_DEPTH_SIZE] = S_028000_PITCH_TILE_MAX(pitch) |
+ S_028000_SLICE_TILE_MAX(slice);
+ if (radeon_state_pm4(rstate)) {
+ radeon_state_decref(rstate);
+ return NULL;
+ }
+ return rstate;
}
-static void *r600_create_rs_state(struct pipe_context *ctx,
- const struct pipe_rasterizer_state *state)
+static struct radeon_state *r600_rasterizer(struct r600_context *rctx)
{
- struct r600_screen *rscreen = r600_screen(ctx->screen);
- struct r600_context *rctx = r600_context(ctx);
+ const struct pipe_rasterizer_state *state = &rctx->rasterizer->state.rasterizer;
+ const struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
+ struct r600_screen *rscreen = rctx->screen;
struct radeon_state *rstate;
+ float offset_units = 0, offset_scale = 0;
+ char depth = 0;
+ unsigned offset_db_fmt_cntl = 0;
+ unsigned tmp;
+ unsigned prov_vtx = 1;
+ if (fb->zsbuf) {
+ offset_units = state->offset_units;
+ offset_scale = state->offset_scale * 12.0f;
+ switch (fb->zsbuf->texture->format) {
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ depth = -24;
+ offset_units *= 2.0f;
+ break;
+ case PIPE_FORMAT_Z32_FLOAT:
+ depth = -23;
+ offset_units *= 1.0f;
+ offset_db_fmt_cntl |= S_028DF8_POLY_OFFSET_DB_IS_FLOAT_FMT(1);
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ depth = -16;
+ offset_units *= 4.0f;
+ break;
+ default:
+ R600_ERR("unsupported %d\n", fb->zsbuf->texture->format);
+ return NULL;
+ }
+ }
+ offset_db_fmt_cntl |= S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS(depth);
+
+ if (state->flatshade_first)
+ prov_vtx = 0;
rctx->flat_shade = state->flatshade;
rstate = radeon_state(rscreen->rw, R600_RASTERIZER_TYPE, R600_RASTERIZER);
if (rstate == NULL)
return NULL;
rstate->states[R600_RASTERIZER__SPI_INTERP_CONTROL_0] = 0x00000001;
+ if (state->sprite_coord_enable) {
+ rstate->states[R600_RASTERIZER__SPI_INTERP_CONTROL_0] |=
+ S_0286D4_PNT_SPRITE_ENA(1) |
+ S_0286D4_PNT_SPRITE_OVRD_X(2) |
+ S_0286D4_PNT_SPRITE_OVRD_Y(3) |
+ S_0286D4_PNT_SPRITE_OVRD_Z(0) |
+ S_0286D4_PNT_SPRITE_OVRD_W(1);
+ if (state->sprite_coord_mode != PIPE_SPRITE_COORD_UPPER_LEFT) {
+ rstate->states[R600_RASTERIZER__SPI_INTERP_CONTROL_0] |=
+ S_0286D4_PNT_SPRITE_TOP_1(1);
+ }
+ }
rstate->states[R600_RASTERIZER__PA_CL_CLIP_CNTL] = 0x00000000;
- rstate->states[R600_RASTERIZER__PA_SU_SC_MODE_CNTL] = 0x00080000;
- rstate->states[R600_RASTERIZER__PA_CL_VS_OUT_CNTL] = 0x00000000;
+ rstate->states[R600_RASTERIZER__PA_SU_SC_MODE_CNTL] =
+ S_028814_PROVOKING_VTX_LAST(prov_vtx) |
+ S_028814_CULL_FRONT((state->cull_face & PIPE_FACE_FRONT) ? 1 : 0) |
+ S_028814_CULL_BACK((state->cull_face & PIPE_FACE_BACK) ? 1 : 0) |
+ S_028814_FACE(!state->front_ccw) |
+ S_028814_POLY_OFFSET_FRONT_ENABLE(state->offset_tri) |
+ S_028814_POLY_OFFSET_BACK_ENABLE(state->offset_tri) |
+ S_028814_POLY_OFFSET_PARA_ENABLE(state->offset_tri);
+ rstate->states[R600_RASTERIZER__PA_CL_VS_OUT_CNTL] =
+ S_02881C_USE_VTX_POINT_SIZE(state->point_size_per_vertex) |
+ S_02881C_VS_OUT_MISC_VEC_ENA(state->point_size_per_vertex);
rstate->states[R600_RASTERIZER__PA_CL_NANINF_CNTL] = 0x00000000;
- rstate->states[R600_RASTERIZER__PA_SU_POINT_SIZE] = 0x00080008;
- rstate->states[R600_RASTERIZER__PA_SU_POINT_MINMAX] = 0x00000000;
+ /* point size 12.4 fixed point */
+ tmp = (unsigned)(state->point_size * 8.0 / 2.0);
+ rstate->states[R600_RASTERIZER__PA_SU_POINT_SIZE] = S_028A00_HEIGHT(tmp) | S_028A00_WIDTH(tmp);
+ rstate->states[R600_RASTERIZER__PA_SU_POINT_MINMAX] = 0x80000000;
rstate->states[R600_RASTERIZER__PA_SU_LINE_CNTL] = 0x00000008;
rstate->states[R600_RASTERIZER__PA_SC_LINE_STIPPLE] = 0x00000005;
rstate->states[R600_RASTERIZER__PA_SC_MPASS_PS_CNTL] = 0x00000000;
@@ -205,12 +846,12 @@ static void *r600_create_rs_state(struct pipe_context *ctx,
rstate->states[R600_RASTERIZER__PA_CL_GB_VERT_DISC_ADJ] = 0x3F800000;
rstate->states[R600_RASTERIZER__PA_CL_GB_HORZ_CLIP_ADJ] = 0x3F800000;
rstate->states[R600_RASTERIZER__PA_CL_GB_HORZ_DISC_ADJ] = 0x3F800000;
- rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_DB_FMT_CNTL] = 0x00000000;
+ rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_DB_FMT_CNTL] = offset_db_fmt_cntl;
rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_CLAMP] = 0x00000000;
- rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_FRONT_SCALE] = 0x00000000;
- rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_FRONT_OFFSET] = 0x00000000;
- rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_BACK_SCALE] = 0x00000000;
- rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_BACK_OFFSET] = 0x00000000;
+ rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_FRONT_SCALE] = fui(offset_scale);
+ rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_FRONT_OFFSET] = fui(offset_units);
+ rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_BACK_SCALE] = fui(offset_scale);
+ rstate->states[R600_RASTERIZER__PA_SU_POLY_OFFSET_BACK_OFFSET] = fui(offset_units);
if (radeon_state_pm4(rstate)) {
radeon_state_decref(rstate);
return NULL;
@@ -218,64 +859,31 @@ static void *r600_create_rs_state(struct pipe_context *ctx,
return rstate;
}
-static void r600_bind_rs_state(struct pipe_context *ctx, void *state)
+static struct radeon_state *r600_scissor(struct r600_context *rctx)
{
- struct r600_context *rctx = r600_context(ctx);
- radeon_draw_set(rctx->draw, state);
-}
-
-static void *r600_create_sampler_state(struct pipe_context *ctx,
- const struct pipe_sampler_state *state)
-{
- return NULL;
-}
-
-static void r600_bind_sampler_states(struct pipe_context *ctx,
- unsigned count, void **states)
-{
-}
-
-static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *ctx,
- struct pipe_resource *texture,
- const struct pipe_sampler_view *templ)
-{
- struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
-
- *view = *templ;
- return view;
-}
-
-static void r600_sampler_view_destroy(struct pipe_context *ctx,
- struct pipe_sampler_view *view)
-{
- FREE(view);
-}
-
-static void r600_set_fragment_sampler_views(struct pipe_context *ctx,
- unsigned count,
- struct pipe_sampler_view **views)
-{
-}
-
-static void r600_set_vertex_sampler_views(struct pipe_context *ctx,
- unsigned count,
- struct pipe_sampler_view **views)
-{
-}
-
-static void r600_set_scissor_state(struct pipe_context *ctx,
- const struct pipe_scissor_state *state)
-{
- struct r600_screen *rscreen = r600_screen(ctx->screen);
- struct r600_context *rctx = r600_context(ctx);
+ const struct pipe_scissor_state *state = &rctx->scissor->state.scissor;
+ const struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
+ struct r600_screen *rscreen = rctx->screen;
struct radeon_state *rstate;
+ unsigned minx, maxx, miny, maxy;
u32 tl, br;
- tl = S_028240_TL_X(state->minx) | S_028240_TL_Y(state->miny) | S_028240_WINDOW_OFFSET_DISABLE(1);
- br = S_028244_BR_X(state->maxx) | S_028244_BR_Y(state->maxy);
+ if (state == NULL) {
+ minx = 0;
+ miny = 0;
+ maxx = fb->cbufs[0]->width;
+ maxy = fb->cbufs[0]->height;
+ } else {
+ minx = state->minx;
+ miny = state->miny;
+ maxx = state->maxx;
+ maxy = state->maxy;
+ }
+ tl = S_028240_TL_X(minx) | S_028240_TL_Y(miny) | S_028240_WINDOW_OFFSET_DISABLE(1);
+ br = S_028244_BR_X(maxx) | S_028244_BR_Y(maxy);
rstate = radeon_state(rscreen->rw, R600_SCISSOR_TYPE, R600_SCISSOR);
if (rstate == NULL)
- return;
+ return NULL;
rstate->states[R600_SCISSOR__PA_SC_SCREEN_SCISSOR_TL] = tl;
rstate->states[R600_SCISSOR__PA_SC_SCREEN_SCISSOR_BR] = br;
rstate->states[R600_SCISSOR__PA_SC_WINDOW_OFFSET] = 0x00000000;
@@ -297,97 +905,104 @@ static void r600_set_scissor_state(struct pipe_context *ctx,
rstate->states[R600_SCISSOR__PA_SC_VPORT_SCISSOR_0_BR] = br;
if (radeon_state_pm4(rstate)) {
radeon_state_decref(rstate);
- return;
+ return NULL;
}
- radeon_draw_set_new(rctx->draw, rstate);
+ return rstate;
}
-static void r600_set_viewport_state(struct pipe_context *ctx,
- const struct pipe_viewport_state *state)
+static struct radeon_state *r600_viewport(struct r600_context *rctx)
{
- struct r600_screen *rscreen = r600_screen(ctx->screen);
- struct r600_context *rctx = r600_context(ctx);
+ const struct pipe_viewport_state *state = &rctx->viewport->state.viewport;
+ struct r600_screen *rscreen = rctx->screen;
struct radeon_state *rstate;
rstate = radeon_state(rscreen->rw, R600_VIEWPORT_TYPE, R600_VIEWPORT);
if (rstate == NULL)
- return;
+ return NULL;
rstate->states[R600_VIEWPORT__PA_SC_VPORT_ZMIN_0] = 0x00000000;
rstate->states[R600_VIEWPORT__PA_SC_VPORT_ZMAX_0] = 0x3F800000;
- rstate->states[R600_VIEWPORT__PA_CL_VPORT_XSCALE_0] = r600_float_to_u32(state->scale[0]);
- rstate->states[R600_VIEWPORT__PA_CL_VPORT_YSCALE_0] = r600_float_to_u32(state->scale[1]);
- rstate->states[R600_VIEWPORT__PA_CL_VPORT_ZSCALE_0] = r600_float_to_u32(state->scale[2]);
- rstate->states[R600_VIEWPORT__PA_CL_VPORT_XOFFSET_0] = r600_float_to_u32(state->translate[0]);
- rstate->states[R600_VIEWPORT__PA_CL_VPORT_YOFFSET_0] = r600_float_to_u32(state->translate[1]);
- rstate->states[R600_VIEWPORT__PA_CL_VPORT_ZOFFSET_0] = r600_float_to_u32(state->translate[2]);
+ rstate->states[R600_VIEWPORT__PA_CL_VPORT_XSCALE_0] = fui(state->scale[0]);
+ rstate->states[R600_VIEWPORT__PA_CL_VPORT_YSCALE_0] = fui(state->scale[1]);
+ rstate->states[R600_VIEWPORT__PA_CL_VPORT_ZSCALE_0] = fui(state->scale[2]);
+ rstate->states[R600_VIEWPORT__PA_CL_VPORT_XOFFSET_0] = fui(state->translate[0]);
+ rstate->states[R600_VIEWPORT__PA_CL_VPORT_YOFFSET_0] = fui(state->translate[1]);
+ rstate->states[R600_VIEWPORT__PA_CL_VPORT_ZOFFSET_0] = fui(state->translate[2]);
rstate->states[R600_VIEWPORT__PA_CL_VTE_CNTL] = 0x0000043F;
if (radeon_state_pm4(rstate)) {
radeon_state_decref(rstate);
- return;
+ return NULL;
}
- radeon_draw_set_new(rctx->draw, rstate);
- rctx->viewport = *state;
-}
-
-static void r600_set_vertex_buffers(struct pipe_context *ctx,
- unsigned count,
- const struct pipe_vertex_buffer *buffers)
-{
- struct r600_context *rctx = r600_context(ctx);
-
- memcpy(rctx->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count);
- rctx->nvertex_buffer = count;
+ return rstate;
}
-
-static void *r600_create_vertex_elements_state(struct pipe_context *ctx,
- unsigned count,
- const struct pipe_vertex_element *elements)
+static struct radeon_state *r600_dsa(struct r600_context *rctx)
{
- struct r600_vertex_elements_state *v = CALLOC_STRUCT(r600_vertex_elements_state);
+ const struct pipe_depth_stencil_alpha_state *state = &rctx->dsa->state.dsa;
+ const struct pipe_stencil_ref *stencil_ref = &rctx->stencil_ref->state.stencil_ref;
+ struct r600_screen *rscreen = rctx->screen;
+ unsigned db_depth_control, alpha_test_control, alpha_ref, db_shader_control;
+ unsigned stencil_ref_mask, stencil_ref_mask_bf;
+ struct r600_shader *rshader = &rctx->ps_shader->shader;
+ struct radeon_state *rstate;
+ int i;
- assert(count < 32);
- v->count = count;
- memcpy(v->elements, elements, count * sizeof(struct pipe_vertex_element));
- return v;
-}
+ rstate = radeon_state(rscreen->rw, R600_DSA_TYPE, R600_DSA);
+ if (rstate == NULL)
+ return NULL;
-static void r600_bind_vertex_elements_state(struct pipe_context *ctx, void *state)
-{
- struct r600_context *rctx = r600_context(ctx);
- struct r600_vertex_elements_state *v = (struct r600_vertex_elements_state*)state;
+ db_shader_control = 0x210;
+ for (i = 0; i < rshader->noutput; i++) {
+ if (rshader->output[i].name == TGSI_SEMANTIC_POSITION)
+ db_shader_control |= 1;
+ }
+ stencil_ref_mask = 0;
+ stencil_ref_mask_bf = 0;
+ db_depth_control = S_028800_Z_ENABLE(state->depth.enabled) |
+ S_028800_Z_WRITE_ENABLE(state->depth.writemask) |
+ S_028800_ZFUNC(state->depth.func);
+ /* set stencil enable */
- rctx->vertex_elements = v;
-}
+ if (state->stencil[0].enabled) {
+ db_depth_control |= S_028800_STENCIL_ENABLE(1);
+ db_depth_control |= S_028800_STENCILFUNC(r600_translate_ds_func(state->stencil[0].func));
+ db_depth_control |= S_028800_STENCILFAIL(r600_translate_stencil_op(state->stencil[0].fail_op));
+ db_depth_control |= S_028800_STENCILZPASS(r600_translate_stencil_op(state->stencil[0].zpass_op));
+ db_depth_control |= S_028800_STENCILZFAIL(r600_translate_stencil_op(state->stencil[0].zfail_op));
-static void r600_delete_vertex_elements_state(struct pipe_context *ctx, void *state)
-{
- FREE(state);
-}
+ stencil_ref_mask = S_028430_STENCILMASK(state->stencil[0].valuemask) |
+ S_028430_STENCILWRITEMASK(state->stencil[0].writemask);
+ stencil_ref_mask |= S_028430_STENCILREF(stencil_ref->ref_value[0]);
+ if (state->stencil[1].enabled) {
+ db_depth_control |= S_028800_BACKFACE_ENABLE(1);
+ db_depth_control |= S_028800_STENCILFUNC_BF(r600_translate_ds_func(state->stencil[1].func));
+ db_depth_control |= S_028800_STENCILFAIL_BF(r600_translate_stencil_op(state->stencil[1].fail_op));
+ db_depth_control |= S_028800_STENCILZPASS_BF(r600_translate_stencil_op(state->stencil[1].zpass_op));
+ db_depth_control |= S_028800_STENCILZFAIL_BF(r600_translate_stencil_op(state->stencil[1].zfail_op));
+ stencil_ref_mask_bf = S_028434_STENCILMASK_BF(state->stencil[1].valuemask) |
+ S_028434_STENCILWRITEMASK_BF(state->stencil[1].writemask);
+ stencil_ref_mask_bf |= S_028430_STENCILREF(stencil_ref->ref_value[1]);
+ }
+ }
-static void *r600_create_dsa_state(struct pipe_context *ctx,
- const struct pipe_depth_stencil_alpha_state *state)
-{
- struct r600_screen *rscreen = r600_screen(ctx->screen);
- struct radeon_state *rstate;
- unsigned db_depth_control;
+ alpha_test_control = 0;
+ alpha_ref = 0;
+ if (state->alpha.enabled) {
+ alpha_test_control = S_028410_ALPHA_FUNC(state->alpha.func);
+ alpha_test_control |= S_028410_ALPHA_TEST_ENABLE(1);
+ alpha_ref = fui(state->alpha.ref_value);
+ }
- rstate = radeon_state(rscreen->rw, R600_DSA_TYPE, R600_DSA);
- if (rstate == NULL)
- return NULL;
- db_depth_control = 0x00700700 | S_028800_Z_ENABLE(state->depth.enabled) | S_028800_Z_WRITE_ENABLE(state->depth.writemask) | S_028800_ZFUNC(state->depth.func);
-
rstate->states[R600_DSA__DB_STENCIL_CLEAR] = 0x00000000;
rstate->states[R600_DSA__DB_DEPTH_CLEAR] = 0x3F800000;
- rstate->states[R600_DSA__SX_ALPHA_TEST_CONTROL] = 0x00000000;
- rstate->states[R600_DSA__DB_STENCILREFMASK] = 0xFFFFFF00;
- rstate->states[R600_DSA__DB_STENCILREFMASK_BF] = 0xFFFFFF00;
- rstate->states[R600_DSA__SX_ALPHA_REF] = 0x00000000;
+ rstate->states[R600_DSA__SX_ALPHA_TEST_CONTROL] = alpha_test_control;
+ rstate->states[R600_DSA__DB_STENCILREFMASK] = stencil_ref_mask;
+ rstate->states[R600_DSA__DB_STENCILREFMASK_BF] = stencil_ref_mask_bf;
+ rstate->states[R600_DSA__SX_ALPHA_REF] = alpha_ref;
rstate->states[R600_DSA__SPI_FOG_FUNC_SCALE] = 0x00000000;
rstate->states[R600_DSA__SPI_FOG_FUNC_BIAS] = 0x00000000;
rstate->states[R600_DSA__SPI_FOG_CNTL] = 0x00000000;
rstate->states[R600_DSA__DB_DEPTH_CONTROL] = db_depth_control;
- rstate->states[R600_DSA__DB_SHADER_CONTROL] = 0x00000210;
+ rstate->states[R600_DSA__DB_SHADER_CONTROL] = db_shader_control;
rstate->states[R600_DSA__DB_RENDER_CONTROL] = 0x00000060;
rstate->states[R600_DSA__DB_RENDER_OVERRIDE] = 0x0000002A;
rstate->states[R600_DSA__DB_SRESULTS_COMPARE_STATE1] = 0x00000000;
@@ -400,105 +1015,390 @@ static void *r600_create_dsa_state(struct pipe_context *ctx,
return rstate;
}
-static void r600_bind_dsa_state(struct pipe_context *ctx, void *state)
+static inline unsigned r600_tex_wrap(unsigned wrap)
{
- struct r600_context *rctx = r600_context(ctx);
- radeon_draw_set(rctx->draw, state);
+ switch (wrap) {
+ default:
+ case PIPE_TEX_WRAP_REPEAT:
+ return V_03C000_SQ_TEX_WRAP;
+ case PIPE_TEX_WRAP_CLAMP:
+ return V_03C000_SQ_TEX_CLAMP_LAST_TEXEL;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ return V_03C000_SQ_TEX_CLAMP_HALF_BORDER;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ return V_03C000_SQ_TEX_CLAMP_BORDER;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ return V_03C000_SQ_TEX_MIRROR;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ return V_03C000_SQ_TEX_MIRROR_ONCE_LAST_TEXEL;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ return V_03C000_SQ_TEX_MIRROR_ONCE_HALF_BORDER;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ return V_03C000_SQ_TEX_MIRROR_ONCE_BORDER;
+ }
}
-static void r600_set_constant_buffer(struct pipe_context *ctx,
- uint shader, uint index,
- struct pipe_resource *buffer)
+static inline unsigned r600_tex_filter(unsigned filter)
{
- struct r600_screen *rscreen = r600_screen(ctx->screen);
- struct r600_context *rctx = r600_context(ctx);
- unsigned nconstant = 0, i, type, id;
+ switch (filter) {
+ default:
+ case PIPE_TEX_FILTER_NEAREST:
+ return V_03C000_SQ_TEX_XY_FILTER_POINT;
+ case PIPE_TEX_FILTER_LINEAR:
+ return V_03C000_SQ_TEX_XY_FILTER_BILINEAR;
+ }
+}
+
+static inline unsigned r600_tex_mipfilter(unsigned filter)
+{
+ switch (filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ return V_03C000_SQ_TEX_Z_FILTER_POINT;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ return V_03C000_SQ_TEX_Z_FILTER_LINEAR;
+ default:
+ case PIPE_TEX_MIPFILTER_NONE:
+ return V_03C000_SQ_TEX_Z_FILTER_NONE;
+ }
+}
+
+static inline unsigned r600_tex_compare(unsigned compare)
+{
+ switch (compare) {
+ default:
+ case PIPE_FUNC_NEVER:
+ return V_03C000_SQ_TEX_DEPTH_COMPARE_NEVER;
+ case PIPE_FUNC_LESS:
+ return V_03C000_SQ_TEX_DEPTH_COMPARE_LESS;
+ case PIPE_FUNC_EQUAL:
+ return V_03C000_SQ_TEX_DEPTH_COMPARE_EQUAL;
+ case PIPE_FUNC_LEQUAL:
+ return V_03C000_SQ_TEX_DEPTH_COMPARE_LESSEQUAL;
+ case PIPE_FUNC_GREATER:
+ return V_03C000_SQ_TEX_DEPTH_COMPARE_GREATER;
+ case PIPE_FUNC_NOTEQUAL:
+ return V_03C000_SQ_TEX_DEPTH_COMPARE_NOTEQUAL;
+ case PIPE_FUNC_GEQUAL:
+ return V_03C000_SQ_TEX_DEPTH_COMPARE_GREATEREQUAL;
+ case PIPE_FUNC_ALWAYS:
+ return V_03C000_SQ_TEX_DEPTH_COMPARE_ALWAYS;
+ }
+}
+
+static INLINE u32 S_FIXED(float value, u32 frac_bits)
+{
+ return value * (1 << frac_bits);
+}
+
+static struct radeon_state *r600_sampler(struct r600_context *rctx,
+ const struct pipe_sampler_state *state,
+ unsigned id)
+{
+ struct r600_screen *rscreen = rctx->screen;
struct radeon_state *rstate;
- struct pipe_transfer *transfer;
- u32 *ptr;
- switch (shader) {
- case PIPE_SHADER_VERTEX:
- id = R600_VS_CONSTANT;
- type = R600_VS_CONSTANT_TYPE;
- break;
- case PIPE_SHADER_FRAGMENT:
- id = R600_PS_CONSTANT;
- type = R600_PS_CONSTANT_TYPE;
- break;
+ rstate = radeon_state(rscreen->rw, R600_PS_SAMPLER_TYPE, id);
+ if (rstate == NULL)
+ return NULL;
+ rstate->states[R600_PS_SAMPLER__SQ_TEX_SAMPLER_WORD0_0] =
+ S_03C000_CLAMP_X(r600_tex_wrap(state->wrap_s)) |
+ S_03C000_CLAMP_Y(r600_tex_wrap(state->wrap_t)) |
+ S_03C000_CLAMP_Z(r600_tex_wrap(state->wrap_r)) |
+ S_03C000_XY_MAG_FILTER(r600_tex_filter(state->mag_img_filter)) |
+ S_03C000_XY_MIN_FILTER(r600_tex_filter(state->min_img_filter)) |
+ S_03C000_MIP_FILTER(r600_tex_mipfilter(state->min_mip_filter)) |
+ S_03C000_DEPTH_COMPARE_FUNCTION(r600_tex_compare(state->compare_func));
+ /* FIXME LOD it depends on texture base level ... */
+ rstate->states[R600_PS_SAMPLER__SQ_TEX_SAMPLER_WORD1_0] =
+ S_03C004_MIN_LOD(S_FIXED(CLAMP(state->min_lod, 0, 15), 6)) |
+ S_03C004_MAX_LOD(S_FIXED(CLAMP(state->max_lod, 0, 15), 6)) |
+ S_03C004_LOD_BIAS(S_FIXED(CLAMP(state->lod_bias, -16, 16), 6));
+ rstate->states[R600_PS_SAMPLER__SQ_TEX_SAMPLER_WORD2_0] = S_03C008_TYPE(1);
+ if (radeon_state_pm4(rstate)) {
+ radeon_state_decref(rstate);
+ return NULL;
+ }
+ return rstate;
+}
+
+static inline unsigned r600_tex_swizzle(unsigned swizzle)
+{
+ switch (swizzle) {
+ case PIPE_SWIZZLE_RED:
+ return V_038010_SQ_SEL_X;
+ case PIPE_SWIZZLE_GREEN:
+ return V_038010_SQ_SEL_Y;
+ case PIPE_SWIZZLE_BLUE:
+ return V_038010_SQ_SEL_Z;
+ case PIPE_SWIZZLE_ALPHA:
+ return V_038010_SQ_SEL_W;
+ case PIPE_SWIZZLE_ZERO:
+ return V_038010_SQ_SEL_0;
default:
- fprintf(stderr, "%s:%d unsupported %d\n", __func__, __LINE__, shader);
- return;
+ case PIPE_SWIZZLE_ONE:
+ return V_038010_SQ_SEL_1;
}
- if (buffer && buffer->width0 > 0) {
- nconstant = buffer->width0 / 16;
- ptr = pipe_buffer_map(ctx, buffer, PIPE_TRANSFER_READ, &transfer);
- if (ptr == NULL)
- return;
- for (i = 0; i < nconstant; i++) {
- rstate = radeon_state(rscreen->rw, type, id + i);
- if (rstate == NULL)
- return;
- rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT0_0] = ptr[i * 4 + 0];
- rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT1_0] = ptr[i * 4 + 1];
- rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT2_0] = ptr[i * 4 + 2];
- rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT3_0] = ptr[i * 4 + 3];
- if (radeon_state_pm4(rstate))
- return;
- if (radeon_draw_set_new(rctx->draw, rstate))
- return;
- }
- pipe_buffer_unmap(ctx, buffer, transfer);
+}
+
+static inline unsigned r600_format_type(unsigned format_type)
+{
+ switch (format_type) {
+ default:
+ case UTIL_FORMAT_TYPE_UNSIGNED:
+ return V_038010_SQ_FORMAT_COMP_UNSIGNED;
+ case UTIL_FORMAT_TYPE_SIGNED:
+ return V_038010_SQ_FORMAT_COMP_SIGNED;
+ case UTIL_FORMAT_TYPE_FIXED:
+ return V_038010_SQ_FORMAT_COMP_UNSIGNED_BIASED;
}
}
-static void r600_set_stencil_ref(struct pipe_context *ctx,
- const struct pipe_stencil_ref *sr)
+static inline unsigned r600_tex_dim(unsigned dim)
{
- struct r600_context *rctx = r600_context(ctx);
- rctx->stencil_ref = *sr;
+ switch (dim) {
+ default:
+ case PIPE_TEXTURE_1D:
+ return V_038000_SQ_TEX_DIM_1D;
+ case PIPE_TEXTURE_2D:
+ return V_038000_SQ_TEX_DIM_2D;
+ case PIPE_TEXTURE_3D:
+ return V_038000_SQ_TEX_DIM_3D;
+ case PIPE_TEXTURE_CUBE:
+ return V_038000_SQ_TEX_DIM_CUBEMAP;
+ }
}
-static void r600_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
+static struct radeon_state *r600_resource(struct r600_context *rctx,
+ const struct pipe_sampler_view *view,
+ unsigned id)
{
+ struct r600_screen *rscreen = rctx->screen;
+ const struct util_format_description *desc;
+ struct r600_resource_texture *tmp;
+ struct r600_resource *rbuffer;
+ struct radeon_state *rstate;
+ unsigned format;
+ uint32_t word4 = 0, yuv_format = 0;
+ unsigned char swizzle[4];
+
+ swizzle[0] = view->swizzle_r;
+ swizzle[1] = view->swizzle_g;
+ swizzle[2] = view->swizzle_b;
+ swizzle[3] = view->swizzle_a;
+ format = r600_translate_texformat(view->texture->format,
+ swizzle,
+ &word4, &yuv_format);
+ if (format == ~0)
+ return NULL;
+ desc = util_format_description(view->texture->format);
+ if (desc == NULL) {
+ R600_ERR("unknow format %d\n", view->texture->format);
+ return NULL;
+ }
+ rstate = radeon_state(rscreen->rw, R600_PS_RESOURCE_TYPE, id);
+ if (rstate == NULL) {
+ return NULL;
+ }
+ tmp = (struct r600_resource_texture*)view->texture;
+ rbuffer = &tmp->resource;
+ rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
+ rstate->bo[1] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
+ rstate->nbo = 2;
+ rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+ rstate->placement[1] = RADEON_GEM_DOMAIN_GTT;
+ rstate->placement[2] = RADEON_GEM_DOMAIN_GTT;
+ rstate->placement[3] = RADEON_GEM_DOMAIN_GTT;
+
+ /* FIXME properly handle first level != 0 */
+ rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD0] =
+ S_038000_DIM(r600_tex_dim(view->texture->target)) |
+ S_038000_PITCH(((tmp->pitch[0] / tmp->bpt) / 8) - 1) |
+ S_038000_TEX_WIDTH(view->texture->width0 - 1);
+ rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD1] =
+ S_038004_TEX_HEIGHT(view->texture->height0 - 1) |
+ S_038004_TEX_DEPTH(view->texture->depth0 - 1) |
+ S_038004_DATA_FORMAT(format);
+ rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD2] = 0;
+ rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD3] = tmp->offset[1] >> 8;
+ rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD4] =
+ word4 |
+ S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_NORM) |
+ S_038010_SRF_MODE_ALL(V_038010_SFR_MODE_NO_ZERO) |
+ S_038010_REQUEST_SIZE(1) |
+ S_038010_BASE_LEVEL(view->first_level);
+ rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD5] =
+ S_038014_LAST_LEVEL(view->last_level) |
+ S_038014_BASE_ARRAY(0) |
+ S_038014_LAST_ARRAY(0);
+ rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD6] =
+ S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE);
+ if (radeon_state_pm4(rstate)) {
+ radeon_state_decref(rstate);
+ return NULL;
+ }
+ return rstate;
}
-void r600_init_state_functions(struct r600_context *rctx)
+static struct radeon_state *r600_cb_cntl(struct r600_context *rctx)
{
- rctx->context.set_sample_mask = r600_set_sample_mask;
- rctx->context.create_blend_state = r600_create_blend_state;
- rctx->context.bind_blend_state = r600_bind_blend_state;
- rctx->context.delete_blend_state = r600_delete_state;
- rctx->context.set_blend_color = r600_set_blend_color;
- rctx->context.set_clip_state = r600_set_clip_state;
- rctx->context.set_constant_buffer = r600_set_constant_buffer;
- rctx->context.create_depth_stencil_alpha_state = r600_create_dsa_state;
- rctx->context.bind_depth_stencil_alpha_state = r600_bind_dsa_state;
- rctx->context.delete_depth_stencil_alpha_state = r600_delete_state;
- rctx->context.set_framebuffer_state = r600_set_framebuffer_state;
- rctx->context.create_fs_state = r600_create_fs_state;
- rctx->context.bind_fs_state = r600_bind_fs_state;
- rctx->context.delete_fs_state = r600_delete_state;
- rctx->context.set_polygon_stipple = r600_set_polygon_stipple;
- rctx->context.create_rasterizer_state = r600_create_rs_state;
- rctx->context.bind_rasterizer_state = r600_bind_rs_state;
- rctx->context.delete_rasterizer_state = r600_delete_state;
- rctx->context.create_sampler_state = r600_create_sampler_state;
- rctx->context.bind_fragment_sampler_states = r600_bind_sampler_states;
- rctx->context.bind_vertex_sampler_states = r600_bind_sampler_states;
- rctx->context.delete_sampler_state = r600_delete_state;
- rctx->context.create_sampler_view = r600_create_sampler_view;
- rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
- rctx->context.set_fragment_sampler_views = r600_set_fragment_sampler_views;
- rctx->context.set_vertex_sampler_views = r600_set_vertex_sampler_views;
- rctx->context.set_scissor_state = r600_set_scissor_state;
- rctx->context.set_viewport_state = r600_set_viewport_state;
- rctx->context.set_vertex_buffers = r600_set_vertex_buffers;
- rctx->context.create_vertex_elements_state = r600_create_vertex_elements_state;
- rctx->context.bind_vertex_elements_state = r600_bind_vertex_elements_state;
- rctx->context.delete_vertex_elements_state = r600_delete_vertex_elements_state;
- rctx->context.create_vs_state = r600_create_vs_state;
- rctx->context.bind_vs_state = r600_bind_vs_state;
- rctx->context.delete_vs_state = r600_delete_state;
- rctx->context.set_stencil_ref = r600_set_stencil_ref;
+ struct r600_screen *rscreen = rctx->screen;
+ struct radeon_state *rstate;
+ const struct pipe_blend_state *pbs = &rctx->blend->state.blend;
+ int nr_cbufs = rctx->framebuffer->state.framebuffer.nr_cbufs;
+ uint32_t color_control, target_mask, shader_mask;
+ int i;
+
+ target_mask = 0;
+ shader_mask = 0;
+ color_control = S_028808_PER_MRT_BLEND(1);
+
+ for (i = 0; i < nr_cbufs; i++) {
+ shader_mask |= 0xf << (i * 4);
+ }
+
+ if (pbs->logicop_enable) {
+ color_control |= (pbs->logicop_func) << 16;
+ } else {
+ color_control |= (0xcc << 16);
+ }
+
+ if (pbs->independent_blend_enable) {
+ for (i = 0; i < nr_cbufs; i++) {
+ if (pbs->rt[i].blend_enable) {
+ color_control |= S_028808_TARGET_BLEND_ENABLE(1 << i);
+ }
+ target_mask |= (pbs->rt[i].colormask << (4 * i));
+ }
+ } else {
+ for (i = 0; i < nr_cbufs; i++) {
+ if (pbs->rt[0].blend_enable) {
+ color_control |= S_028808_TARGET_BLEND_ENABLE(1 << i);
+ }
+ target_mask |= (pbs->rt[0].colormask << (4 * i));
+ }
+ }
+ rstate = radeon_state(rscreen->rw, R600_CB_CNTL_TYPE, R600_CB_CNTL);
+ rstate->states[R600_CB_CNTL__CB_SHADER_MASK] = shader_mask;
+ rstate->states[R600_CB_CNTL__CB_TARGET_MASK] = target_mask;
+ rstate->states[R600_CB_CNTL__CB_COLOR_CONTROL] = color_control;
+ rstate->states[R600_CB_CNTL__PA_SC_AA_CONFIG] = 0x00000000;
+ rstate->states[R600_CB_CNTL__PA_SC_AA_SAMPLE_LOCS_MCTX] = 0x00000000;
+ rstate->states[R600_CB_CNTL__PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX] = 0x00000000;
+ rstate->states[R600_CB_CNTL__CB_CLRCMP_CONTROL] = 0x01000000;
+ rstate->states[R600_CB_CNTL__CB_CLRCMP_SRC] = 0x00000000;
+ rstate->states[R600_CB_CNTL__CB_CLRCMP_DST] = 0x000000FF;
+ rstate->states[R600_CB_CNTL__CB_CLRCMP_MSK] = 0xFFFFFFFF;
+ rstate->states[R600_CB_CNTL__PA_SC_AA_MASK] = 0xFFFFFFFF;
+ if (radeon_state_pm4(rstate)) {
+ radeon_state_decref(rstate);
+ return NULL;
+ }
+ return rstate;
+}
+
+int r600_context_hw_states(struct r600_context *rctx)
+{
+ unsigned i;
+ int r;
+ int nr_cbufs = rctx->framebuffer->state.framebuffer.nr_cbufs;
+
+ /* free previous TODO determine what need to be updated, what
+ * doesn't
+ */
+ //radeon_state_decref(rctx->hw_states.config);
+ rctx->hw_states.cb_cntl = radeon_state_decref(rctx->hw_states.cb_cntl);
+ rctx->hw_states.db = radeon_state_decref(rctx->hw_states.db);
+ rctx->hw_states.rasterizer = radeon_state_decref(rctx->hw_states.rasterizer);
+ rctx->hw_states.scissor = radeon_state_decref(rctx->hw_states.scissor);
+ rctx->hw_states.dsa = radeon_state_decref(rctx->hw_states.dsa);
+ rctx->hw_states.blend = radeon_state_decref(rctx->hw_states.blend);
+ rctx->hw_states.viewport = radeon_state_decref(rctx->hw_states.viewport);
+ for (i = 0; i < 8; i++) {
+ rctx->hw_states.cb[i] = radeon_state_decref(rctx->hw_states.cb[i]);
+ }
+ for (i = 0; i < rctx->hw_states.ps_nresource; i++) {
+ radeon_state_decref(rctx->hw_states.ps_resource[i]);
+ rctx->hw_states.ps_resource[i] = NULL;
+ }
+ rctx->hw_states.ps_nresource = 0;
+ for (i = 0; i < rctx->hw_states.ps_nsampler; i++) {
+ radeon_state_decref(rctx->hw_states.ps_sampler[i]);
+ rctx->hw_states.ps_sampler[i] = NULL;
+ }
+ rctx->hw_states.ps_nsampler = 0;
+
+ /* build new states */
+ rctx->hw_states.rasterizer = r600_rasterizer(rctx);
+ rctx->hw_states.scissor = r600_scissor(rctx);
+ rctx->hw_states.dsa = r600_dsa(rctx);
+ rctx->hw_states.blend = r600_blend(rctx);
+ rctx->hw_states.viewport = r600_viewport(rctx);
+ for (i = 0; i < nr_cbufs; i++) {
+ rctx->hw_states.cb[i] = r600_cb(rctx, i);
+ }
+ rctx->hw_states.db = r600_db(rctx);
+ rctx->hw_states.cb_cntl = r600_cb_cntl(rctx);
+
+ for (i = 0; i < rctx->ps_nsampler; i++) {
+ if (rctx->ps_sampler[i]) {
+ rctx->hw_states.ps_sampler[i] = r600_sampler(rctx,
+ &rctx->ps_sampler[i]->state.sampler,
+ R600_PS_SAMPLER + i);
+ }
+ }
+ rctx->hw_states.ps_nsampler = rctx->ps_nsampler;
+ for (i = 0; i < rctx->ps_nsampler_view; i++) {
+ if (rctx->ps_sampler_view[i]) {
+ rctx->hw_states.ps_resource[i] = r600_resource(rctx,
+ &rctx->ps_sampler_view[i]->state.sampler_view,
+ R600_PS_RESOURCE + i);
+ }
+ }
+ rctx->hw_states.ps_nresource = rctx->ps_nsampler_view;
+
+ /* bind states */
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.db);
+ if (r)
+ return r;
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.rasterizer);
+ if (r)
+ return r;
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.scissor);
+ if (r)
+ return r;
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.dsa);
+ if (r)
+ return r;
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.blend);
+ if (r)
+ return r;
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.viewport);
+ if (r)
+ return r;
+ for (i = 0; i < nr_cbufs; i++) {
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.cb[i]);
+ if (r)
+ return r;
+ }
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.config);
+ if (r)
+ return r;
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.cb_cntl);
+ if (r)
+ return r;
+ for (i = 0; i < rctx->hw_states.ps_nresource; i++) {
+ if (rctx->hw_states.ps_resource[i]) {
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.ps_resource[i]);
+ if (r)
+ return r;
+ }
+ }
+ for (i = 0; i < rctx->hw_states.ps_nsampler; i++) {
+ if (rctx->hw_states.ps_sampler[i]) {
+ r = radeon_draw_set(rctx->draw, rctx->hw_states.ps_sampler[i]);
+ if (r)
+ return r;
+ }
+ }
+ return 0;
}
diff --git a/src/gallium/drivers/r600/r600_state_inlines.h b/src/gallium/drivers/r600/r600_state_inlines.h
new file mode 100644
index 0000000000..f93c20da35
--- /dev/null
+++ b/src/gallium/drivers/r600/r600_state_inlines.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2010 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef R600_STATE_INLINES_H
+#define R600_STATE_INLINES_H
+
+#include "util/u_format.h"
+#include "r600d.h"
+
+static INLINE uint32_t r600_translate_blend_function(int blend_func)
+{
+ switch (blend_func) {
+ case PIPE_BLEND_ADD:
+ return V_028804_COMB_DST_PLUS_SRC;
+ case PIPE_BLEND_SUBTRACT:
+ return V_028804_COMB_SRC_MINUS_DST;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ return V_028804_COMB_DST_MINUS_SRC;
+ case PIPE_BLEND_MIN:
+ return V_028804_COMB_MIN_DST_SRC;
+ case PIPE_BLEND_MAX:
+ return V_028804_COMB_MAX_DST_SRC;
+ default:
+ R600_ERR("Unknown blend function %d\n", blend_func);
+ assert(0);
+ break;
+ }
+ return 0;
+}
+
+static INLINE uint32_t r600_translate_blend_factor(int blend_fact)
+{
+ switch (blend_fact) {
+ case PIPE_BLENDFACTOR_ONE:
+ return V_028804_BLEND_ONE;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ return V_028804_BLEND_SRC_COLOR;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ return V_028804_BLEND_SRC_ALPHA;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ return V_028804_BLEND_DST_ALPHA;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ return V_028804_BLEND_DST_COLOR;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ return V_028804_BLEND_SRC_ALPHA_SATURATE;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ return V_028804_BLEND_CONST_COLOR;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ return V_028804_BLEND_CONST_ALPHA;
+ case PIPE_BLENDFACTOR_ZERO:
+ return V_028804_BLEND_ZERO;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ return V_028804_BLEND_ONE_MINUS_SRC_COLOR;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ return V_028804_BLEND_ONE_MINUS_SRC_ALPHA;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ return V_028804_BLEND_ONE_MINUS_DST_ALPHA;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ return V_028804_BLEND_ONE_MINUS_DST_COLOR;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ return V_028804_BLEND_ONE_MINUS_CONST_COLOR;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ return V_028804_BLEND_ONE_MINUS_CONST_ALPHA;
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ return V_028804_BLEND_SRC1_COLOR;
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ return V_028804_BLEND_SRC1_ALPHA;
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ return V_028804_BLEND_INV_SRC1_COLOR;
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ return V_028804_BLEND_INV_SRC1_ALPHA;
+ default:
+ R600_ERR("Bad blend factor %d not supported!\n", blend_fact);
+ assert(0);
+ break;
+ }
+ return 0;
+}
+
+static INLINE uint32_t r600_translate_stencil_op(int s_op)
+{
+ switch (s_op) {
+ case PIPE_STENCIL_OP_KEEP:
+ return V_028800_STENCIL_KEEP;
+ case PIPE_STENCIL_OP_ZERO:
+ return V_028800_STENCIL_ZERO;
+ case PIPE_STENCIL_OP_REPLACE:
+ return V_028800_STENCIL_REPLACE;
+ case PIPE_STENCIL_OP_INCR:
+ return V_028800_STENCIL_INCR;
+ case PIPE_STENCIL_OP_DECR:
+ return V_028800_STENCIL_DECR;
+ case PIPE_STENCIL_OP_INCR_WRAP:
+ return V_028800_STENCIL_INCR_WRAP;
+ case PIPE_STENCIL_OP_DECR_WRAP:
+ return V_028800_STENCIL_DECR_WRAP;
+ case PIPE_STENCIL_OP_INVERT:
+ return V_028800_STENCIL_INVERT;
+ default:
+ R600_ERR("Unknown stencil op %d", s_op);
+ assert(0);
+ break;
+ }
+ return 0;
+}
+
+/* translates straight */
+static INLINE uint32_t r600_translate_ds_func(int func)
+{
+ return func;
+}
+
+static uint32_t r600_translate_dbformat(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ return V_028010_DEPTH_16;
+ case PIPE_FORMAT_Z24X8_UNORM:
+ return V_028010_DEPTH_X8_24;
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ return V_028010_DEPTH_8_24;
+ default:
+ return ~0;
+ }
+}
+
+static uint32_t r600_translate_colorswap(enum pipe_format format)
+{
+ switch (format) {
+ /* 8-bit buffers. */
+ case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_R8_UNORM:
+ case PIPE_FORMAT_R8_SNORM:
+ return V_0280A0_SWAP_STD;
+
+ /* 16-bit buffers. */
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ return V_0280A0_SWAP_STD_REV;
+
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
+ return V_0280A0_SWAP_ALT;
+
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
+ case PIPE_FORMAT_B4G4R4X4_UNORM:
+ return V_0280A0_SWAP_ALT;
+ /* 32-bit buffers. */
+
+ case PIPE_FORMAT_A8B8G8R8_SRGB:
+ return V_0280A0_SWAP_STD_REV;
+ case PIPE_FORMAT_B8G8R8A8_SRGB:
+ return V_0280A0_SWAP_ALT;
+
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ return V_0280A0_SWAP_ALT;
+
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ return V_0280A0_SWAP_ALT_REV;
+ case PIPE_FORMAT_R8G8B8A8_SNORM:
+ case PIPE_FORMAT_R8G8B8X8_UNORM:
+ return V_0280A0_SWAP_STD;
+
+ case PIPE_FORMAT_A8B8G8R8_UNORM:
+ case PIPE_FORMAT_X8B8G8R8_UNORM:
+ // case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
+ return V_0280A0_SWAP_STD_REV;
+
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ return V_0280A0_SWAP_STD;
+
+ case PIPE_FORMAT_R10G10B10A2_UNORM:
+ case PIPE_FORMAT_R10G10B10X2_SNORM:
+ case PIPE_FORMAT_B10G10R10A2_UNORM:
+ case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
+ return V_0280A0_SWAP_STD_REV;
+
+ /* 64-bit buffers. */
+ case PIPE_FORMAT_R16G16B16A16_UNORM:
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ // return V_0280A0_COLOR_16_16_16_16;
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ // return V_0280A0_COLOR_16_16_16_16_FLOAT;
+
+ /* 128-bit buffers. */
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ // return V_0280A0_COLOR_32_32_32_32_FLOAT;
+ return 0;
+ default:
+ R600_ERR("unsupported colorswap format %d\n", format);
+ return ~0;
+ }
+ return ~0;
+}
+
+static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
+{
+ switch (format) {
+ /* 8-bit buffers. */
+ case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_R8_UNORM:
+ case PIPE_FORMAT_R8_SNORM:
+ return V_0280A0_COLOR_8;
+
+ /* 16-bit buffers. */
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ return V_0280A0_COLOR_5_6_5;
+
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
+ return V_0280A0_COLOR_1_5_5_5;
+
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
+ case PIPE_FORMAT_B4G4R4X4_UNORM:
+ return V_0280A0_COLOR_4_4_4_4;
+
+ /* 32-bit buffers. */
+ case PIPE_FORMAT_A8B8G8R8_SRGB:
+ case PIPE_FORMAT_A8B8G8R8_UNORM:
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_SRGB:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_R8G8B8A8_SNORM:
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ case PIPE_FORMAT_R8G8B8X8_UNORM:
+ case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
+ case PIPE_FORMAT_X8B8G8R8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ return V_0280A0_COLOR_8_8_8_8;
+
+ case PIPE_FORMAT_R10G10B10A2_UNORM:
+ case PIPE_FORMAT_R10G10B10X2_SNORM:
+ case PIPE_FORMAT_B10G10R10A2_UNORM:
+ case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
+ return V_0280A0_COLOR_10_10_10_2;
+
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ return V_0280A0_COLOR_24_8;
+
+ /* 64-bit buffers. */
+ case PIPE_FORMAT_R16G16B16A16_UNORM:
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ return V_0280A0_COLOR_16_16_16_16;
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ return V_0280A0_COLOR_16_16_16_16_FLOAT;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ return V_0280A0_COLOR_32_32_FLOAT;
+
+ /* 128-bit buffers. */
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ return V_0280A0_COLOR_32_32_32_32_FLOAT;
+
+ /* YUV buffers. */
+ case PIPE_FORMAT_UYVY:
+ case PIPE_FORMAT_YUYV:
+ default:
+ R600_ERR("unsupported color format %d\n", format);
+ return ~0; /* Unsupported. */
+ }
+}
+
+static INLINE boolean r600_is_sampler_format_supported(enum pipe_format format)
+{
+ return r600_translate_texformat(format, NULL, NULL, NULL) != ~0;
+}
+
+static INLINE boolean r600_is_colorbuffer_format_supported(enum pipe_format format)
+{
+ return r600_translate_colorformat(format) != ~0 &&
+ r600_translate_colorswap(format) != ~0;
+}
+
+static INLINE boolean r600_is_zs_format_supported(enum pipe_format format)
+{
+ return r600_translate_dbformat(format) != ~0;
+}
+
+static INLINE boolean r600_is_vertex_format_supported(enum pipe_format format)
+{
+ return r600_translate_colorformat(format) != ~0;
+}
+
+#endif
diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c
index 903cfad80a..30d79ebdd6 100644
--- a/src/gallium/drivers/r600/r600_texture.c
+++ b/src/gallium/drivers/r600/r600_texture.c
@@ -31,15 +31,19 @@
#include <util/u_memory.h>
#include "state_tracker/drm_driver.h"
#include "r600_screen.h"
-#include "r600_texture.h"
+#include "r600_context.h"
+#include "r600_resource.h"
+#include "r600d.h"
extern struct u_resource_vtbl r600_texture_vtbl;
-unsigned long r600_texture_get_offset(struct r600_texture *rtex, unsigned level, unsigned zslice, unsigned face)
+static unsigned long r600_texture_get_offset(struct r600_resource_texture *rtex,
+ unsigned level, unsigned zslice,
+ unsigned face)
{
unsigned long offset = rtex->offset[level];
- switch (rtex->b.b.target) {
+ switch (rtex->resource.base.b.target) {
case PIPE_TEXTURE_3D:
assert(face == 0);
return offset + zslice * rtex->layer_size[level];
@@ -52,67 +56,68 @@ unsigned long r600_texture_get_offset(struct r600_texture *rtex, unsigned level,
}
}
-static void r600_setup_miptree(struct r600_screen *rscreen, struct r600_texture *rtex)
+static void r600_setup_miptree(struct r600_screen *rscreen, struct r600_resource_texture *rtex)
{
- struct pipe_resource *ptex = &rtex->b.b;
- unsigned long w, h, stride, size, layer_size, i, offset;
+ struct pipe_resource *ptex = &rtex->resource.base.b;
+ unsigned long w, h, pitch, size, layer_size, i, offset;
+ rtex->bpt = util_format_get_blocksize(ptex->format);
for (i = 0, offset = 0; i <= ptex->last_level; i++) {
w = u_minify(ptex->width0, i);
h = u_minify(ptex->height0, i);
- stride = align(util_format_get_stride(ptex->format, w), 32);
- layer_size = stride * h;
+ pitch = util_format_get_stride(ptex->format, align(w, 64));
+ layer_size = pitch * h;
if (ptex->target == PIPE_TEXTURE_CUBE)
size = layer_size * 6;
else
size = layer_size * u_minify(ptex->depth0, i);
rtex->offset[i] = offset;
rtex->layer_size[i] = layer_size;
- rtex->pitch[i] = stride / util_format_get_blocksize(ptex->format);
- rtex->stride[i] = stride;
- offset += align(size, 32);
+ rtex->pitch[i] = pitch;
+ offset += size;
}
rtex->size = offset;
}
struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
- const struct pipe_resource *templ)
+ const struct pipe_resource *templ)
{
- struct r600_texture *rtex = CALLOC_STRUCT(r600_texture);
+ struct r600_resource_texture *rtex;
+ struct r600_resource *resource;
struct r600_screen *rscreen = r600_screen(screen);
- struct pipe_resource templ_buf;
+ rtex = CALLOC_STRUCT(r600_resource_texture);
if (!rtex) {
return NULL;
}
- rtex->b.b = *templ;
- rtex->b.vtbl = &r600_texture_vtbl;
- pipe_reference_init(&rtex->b.b.reference, 1);
- rtex->b.b.screen = screen;
+ resource = &rtex->resource;
+ resource->base.b = *templ;
+ resource->base.vtbl = &r600_texture_vtbl;
+ pipe_reference_init(&resource->base.b.reference, 1);
+ resource->base.b.screen = screen;
r600_setup_miptree(rscreen, rtex);
- memset(&templ_buf, 0, sizeof(struct pipe_resource));
- templ_buf.target = PIPE_BUFFER;
- templ_buf.format = PIPE_FORMAT_R8_UNORM;
- templ_buf.usage = templ->usage;
- templ_buf.bind = templ->bind;
- templ_buf.width0 = rtex->size;
- templ_buf.height0 = 1;
- templ_buf.depth0 = 1;
-
- rtex->buffer = screen->resource_create(screen, &templ_buf);
- if (!rtex->buffer) {
+ /* FIXME alignment 4096 enought ? too much ? */
+ resource->domain = r600_domain_from_usage(resource->base.b.bind);
+ resource->bo = radeon_bo(rscreen->rw, 0, rtex->size, 4096, NULL);
+ if (resource->bo == NULL) {
FREE(rtex);
return NULL;
}
- return &rtex->b.b;
+
+ return &resource->base.b;
}
static void r600_texture_destroy(struct pipe_screen *screen,
struct pipe_resource *ptex)
{
- struct r600_texture *rtex = (struct r600_texture*)ptex;
+ struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
+ struct r600_resource *resource = &rtex->resource;
+ struct r600_screen *rscreen = r600_screen(screen);
+ if (resource->bo) {
+ radeon_bo_decref(rscreen->rw, resource->bo);
+ }
FREE(rtex);
}
@@ -121,7 +126,7 @@ static struct pipe_surface *r600_get_tex_surface(struct pipe_screen *screen,
unsigned face, unsigned level,
unsigned zslice, unsigned flags)
{
- struct r600_texture *rtex = (struct r600_texture*)texture;
+ struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
struct pipe_surface *surface = CALLOC_STRUCT(pipe_surface);
unsigned long offset;
@@ -149,71 +154,115 @@ static void r600_tex_surface_destroy(struct pipe_surface *surface)
}
struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
- const struct pipe_resource *base,
+ const struct pipe_resource *templ,
struct winsys_handle *whandle)
{
- struct pipe_resource *buffer;
- struct r600_texture *rtex;
+ struct radeon *rw = (struct radeon*)screen->winsys;
+ struct r600_resource_texture *rtex;
+ struct r600_resource *resource;
+ struct radeon_bo *bo = NULL;
- buffer = r600_buffer_from_handle(screen, whandle);
- if (buffer == NULL) {
+ bo = radeon_bo(rw, whandle->handle, 0, 0, NULL);
+ if (bo == NULL) {
return NULL;
}
/* Support only 2D textures without mipmaps */
- if (base->target != PIPE_TEXTURE_2D || base->depth0 != 1 || base->last_level != 0)
+ if (templ->target != PIPE_TEXTURE_2D || templ->depth0 != 1 || templ->last_level != 0)
return NULL;
- rtex = CALLOC_STRUCT(r600_texture);
+ rtex = CALLOC_STRUCT(r600_resource_texture);
if (rtex == NULL)
return NULL;
- /* one ref already taken */
- rtex->buffer = buffer;
-
- rtex->b.b = *base;
- rtex->b.vtbl = &r600_texture_vtbl;
- pipe_reference_init(&rtex->b.b.reference, 1);
- rtex->b.b.screen = screen;
- rtex->stride_override = whandle->stride;
- rtex->pitch[0] = whandle->stride / util_format_get_blocksize(base->format);
- rtex->stride[0] = whandle->stride;
+ resource = &rtex->resource;
+ resource->base.b = *templ;
+ resource->base.vtbl = &r600_texture_vtbl;
+ pipe_reference_init(&resource->base.b.reference, 1);
+ resource->base.b.screen = screen;
+ resource->bo = bo;
+ rtex->pitch_override = whandle->stride;
+ rtex->bpt = util_format_get_blocksize(templ->format);
+ rtex->pitch[0] = whandle->stride;
rtex->offset[0] = 0;
- rtex->size = align(rtex->stride[0] * base->height0, 32);
+ rtex->size = align(rtex->pitch[0] * templ->height0, 64);
- return &rtex->b.b;
+ return &resource->base.b;
}
-static boolean r600_texture_get_handle(struct pipe_screen* screen,
- struct pipe_resource *texture,
- struct winsys_handle *whandle)
+static unsigned int r600_texture_is_referenced(struct pipe_context *context,
+ struct pipe_resource *texture,
+ unsigned face, unsigned level)
{
- struct r600_screen *rscreen = r600_screen(screen);
- struct r600_texture* rtex = (struct r600_texture*)texture;
+ /* FIXME */
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
- if (!rtex) {
- return FALSE;
- }
+struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
+ struct pipe_resource *texture,
+ struct pipe_subresource sr,
+ unsigned usage,
+ const struct pipe_box *box)
+{
+ struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
+ struct r600_transfer *trans;
- whandle->stride = rtex->stride[0];
+ trans = CALLOC_STRUCT(r600_transfer);
+ if (trans == NULL)
+ return NULL;
+ pipe_resource_reference(&trans->transfer.resource, texture);
+ trans->transfer.sr = sr;
+ trans->transfer.usage = usage;
+ trans->transfer.box = *box;
+ trans->transfer.stride = rtex->pitch[sr.level];
+ trans->offset = r600_texture_get_offset(rtex, sr.level, box->z, sr.face);
+ return &trans->transfer;
+}
- r600_buffer_get_handle(rscreen->rw, rtex->buffer, whandle);
+void r600_texture_transfer_destroy(struct pipe_context *ctx,
+ struct pipe_transfer *trans)
+{
+ pipe_resource_reference(&trans->resource, NULL);
+ FREE(trans);
+}
- return TRUE;
+void* r600_texture_transfer_map(struct pipe_context *ctx,
+ struct pipe_transfer* transfer)
+{
+ struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
+ struct r600_resource *resource;
+ enum pipe_format format = transfer->resource->format;
+ struct r600_screen *rscreen = r600_screen(ctx->screen);
+ char *map;
+
+ r600_flush(ctx, 0, NULL);
+
+ resource = (struct r600_resource *)transfer->resource;
+ if (radeon_bo_map(rscreen->rw, resource->bo)) {
+ return NULL;
+ }
+ radeon_bo_wait(rscreen->rw, resource->bo);
+
+ map = resource->bo->data;
+
+ return map + rtransfer->offset +
+ transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
+ transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
}
-static unsigned int r600_texture_is_referenced(struct pipe_context *context,
- struct pipe_resource *texture,
- unsigned face, unsigned level)
+void r600_texture_transfer_unmap(struct pipe_context *ctx,
+ struct pipe_transfer* transfer)
{
- struct r600_texture *rtex = (struct r600_texture*)texture;
+ struct r600_screen *rscreen = r600_screen(ctx->screen);
+ struct r600_resource *resource;
- return r600_buffer_is_referenced_by_cs(context, rtex->buffer, face, level);
+ resource = (struct r600_resource *)transfer->resource;
+ radeon_bo_unmap(rscreen->rw, resource->bo);
}
struct u_resource_vtbl r600_texture_vtbl =
{
- r600_texture_get_handle, /* get_handle */
+ u_default_resource_get_handle, /* get_handle */
r600_texture_destroy, /* resource_destroy */
r600_texture_is_referenced, /* is_resource_referenced */
r600_texture_get_transfer, /* get_transfer */
@@ -229,3 +278,250 @@ void r600_init_screen_texture_functions(struct pipe_screen *screen)
screen->get_tex_surface = r600_get_tex_surface;
screen->tex_surface_destroy = r600_tex_surface_destroy;
}
+
+static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format,
+ const unsigned char *swizzle_view)
+{
+ unsigned i;
+ unsigned char swizzle[4];
+ unsigned result = 0;
+ const uint32_t swizzle_shift[4] = {
+ 16, 19, 22, 25,
+ };
+ const uint32_t swizzle_bit[4] = {
+ 0, 1, 2, 3,
+ };
+
+ if (swizzle_view) {
+ /* Combine two sets of swizzles. */
+ for (i = 0; i < 4; i++) {
+ swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
+ swizzle_format[swizzle_view[i]] : swizzle_view[i];
+ }
+ } else {
+ memcpy(swizzle, swizzle_format, 4);
+ }
+
+ /* Get swizzle. */
+ for (i = 0; i < 4; i++) {
+ switch (swizzle[i]) {
+ case UTIL_FORMAT_SWIZZLE_Y:
+ result |= swizzle_bit[1] << swizzle_shift[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_Z:
+ result |= swizzle_bit[2] << swizzle_shift[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_W:
+ result |= swizzle_bit[3] << swizzle_shift[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_0:
+ result |= V_038010_SQ_SEL_0 << swizzle_shift[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_1:
+ result |= V_038010_SQ_SEL_1 << swizzle_shift[i];
+ break;
+ default: /* UTIL_FORMAT_SWIZZLE_X */
+ result |= swizzle_bit[0] << swizzle_shift[i];
+ }
+ }
+ return result;
+}
+
+/* texture format translate */
+uint32_t r600_translate_texformat(enum pipe_format format,
+ const unsigned char *swizzle_view,
+ uint32_t *word4_p, uint32_t *yuv_format_p)
+{
+ uint32_t result = 0, word4 = 0, yuv_format = 0;
+ const struct util_format_description *desc;
+ boolean uniform = TRUE;
+ int i;
+ const uint32_t sign_bit[4] = {
+ S_038010_FORMAT_COMP_X(V_038010_SQ_FORMAT_COMP_SIGNED),
+ S_038010_FORMAT_COMP_Y(V_038010_SQ_FORMAT_COMP_SIGNED),
+ S_038010_FORMAT_COMP_Z(V_038010_SQ_FORMAT_COMP_SIGNED),
+ S_038010_FORMAT_COMP_W(V_038010_SQ_FORMAT_COMP_SIGNED)
+ };
+ desc = util_format_description(format);
+
+ /* Colorspace (return non-RGB formats directly). */
+ switch (desc->colorspace) {
+ /* Depth stencil formats */
+ case UTIL_FORMAT_COLORSPACE_ZS:
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ result = V_028010_DEPTH_16;
+ goto out_word4;
+ case PIPE_FORMAT_Z24X8_UNORM:
+ result = V_028010_DEPTH_X8_24;
+ goto out_word4;
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ result = V_028010_DEPTH_8_24;
+ goto out_word4;
+ default:
+ goto out_unknown;
+ }
+
+ case UTIL_FORMAT_COLORSPACE_YUV:
+ yuv_format |= (1 << 30);
+ switch (format) {
+ case PIPE_FORMAT_UYVY:
+ case PIPE_FORMAT_YUYV:
+ default:
+ break;
+ }
+ goto out_unknown; /* TODO */
+
+ case UTIL_FORMAT_COLORSPACE_SRGB:
+ word4 |= S_038010_FORCE_DEGAMMA(1);
+ if (format == PIPE_FORMAT_L8A8_SRGB || format == PIPE_FORMAT_L8_SRGB)
+ goto out_unknown; /* fails for some reason - TODO */
+ break;
+
+ default:
+ break;
+ }
+
+ word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view);
+
+ /* S3TC formats. TODO */
+ if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
+ goto out_unknown;
+ }
+
+
+ for (i = 0; i < desc->nr_channels; i++) {
+ if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
+ word4 |= sign_bit[i];
+ }
+ }
+
+ /* R8G8Bx_SNORM - TODO CxV8U8 */
+
+ /* RGTC - TODO */
+
+ /* See whether the components are of the same size. */
+ for (i = 1; i < desc->nr_channels; i++) {
+ uniform = uniform && desc->channel[0].size == desc->channel[i].size;
+ }
+
+ /* Non-uniform formats. */
+ if (!uniform) {
+ switch(desc->nr_channels) {
+ case 3:
+ if (desc->channel[0].size == 5 &&
+ desc->channel[1].size == 6 &&
+ desc->channel[2].size == 5) {
+ result |= V_0280A0_COLOR_5_6_5;
+ goto out_word4;
+ }
+ goto out_unknown;
+ case 4:
+ if (desc->channel[0].size == 5 &&
+ desc->channel[1].size == 5 &&
+ desc->channel[2].size == 5 &&
+ desc->channel[3].size == 1) {
+ result |= V_0280A0_COLOR_1_5_5_5;
+ goto out_word4;
+ }
+ if (desc->channel[0].size == 10 &&
+ desc->channel[1].size == 10 &&
+ desc->channel[2].size == 10 &&
+ desc->channel[3].size == 2) {
+ result |= V_0280A0_COLOR_10_10_10_2;
+ goto out_word4;
+ }
+ goto out_unknown;
+ }
+ goto out_unknown;
+ }
+
+ /* uniform formats */
+ switch (desc->channel[0].type) {
+ case UTIL_FORMAT_TYPE_UNSIGNED:
+ case UTIL_FORMAT_TYPE_SIGNED:
+ if (!desc->channel[0].normalized &&
+ desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
+ goto out_unknown;
+ }
+
+ switch (desc->channel[0].size) {
+ case 4:
+ switch (desc->nr_channels) {
+ case 2:
+ result |= V_0280A0_COLOR_4_4;
+ goto out_word4;
+ case 4:
+ result |= V_0280A0_COLOR_4_4_4_4;
+ goto out_word4;
+ }
+ goto out_unknown;
+ case 8:
+ switch (desc->nr_channels) {
+ case 1:
+ result |= V_0280A0_COLOR_8;
+ goto out_word4;
+ case 2:
+ result |= V_0280A0_COLOR_8_8;
+ goto out_word4;
+ case 4:
+ result |= V_0280A0_COLOR_8_8_8_8;
+ goto out_word4;
+ }
+ goto out_unknown;
+ case 16:
+ switch (desc->nr_channels) {
+ case 1:
+ result |= V_0280A0_COLOR_16;
+ goto out_word4;
+ case 2:
+ result |= V_0280A0_COLOR_16_16;
+ goto out_word4;
+ case 4:
+ result |= V_0280A0_COLOR_16_16_16_16;
+ goto out_word4;
+ }
+ }
+ goto out_unknown;
+
+ case UTIL_FORMAT_TYPE_FLOAT:
+ switch (desc->channel[0].size) {
+ case 16:
+ switch (desc->nr_channels) {
+ case 1:
+ result |= V_0280A0_COLOR_16_FLOAT;
+ goto out_word4;
+ case 2:
+ result |= V_0280A0_COLOR_16_16_FLOAT;
+ goto out_word4;
+ case 4:
+ result |= V_0280A0_COLOR_16_16_16_16_FLOAT;
+ goto out_word4;
+ }
+ goto out_unknown;
+ case 32:
+ switch (desc->nr_channels) {
+ case 1:
+ result |= V_0280A0_COLOR_32_FLOAT;
+ goto out_word4;
+ case 2:
+ result |= V_0280A0_COLOR_32_32_FLOAT;
+ goto out_word4;
+ case 4:
+ result |= V_0280A0_COLOR_32_32_32_32_FLOAT;
+ goto out_word4;
+ }
+ }
+
+ }
+out_word4:
+ if (word4_p)
+ *word4_p = word4;
+ if (yuv_format_p)
+ *yuv_format_p = yuv_format;
+// fprintf(stderr,"returning %08x %08x %08x\n", result, word4, yuv_format);
+ return result;
+out_unknown:
+// R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format));
+ return ~0;
+}
diff --git a/src/gallium/drivers/r600/r600_texture.h b/src/gallium/drivers/r600/r600_texture.h
deleted file mode 100644
index 9bc08d6b04..0000000000
--- a/src/gallium/drivers/r600/r600_texture.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2010 Jerome Glisse <glisse@freedesktop.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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef R600_TEXTURE_H
-#define R600_TEXTURE_H
-
-#include <pipe/p_state.h>
-
-struct r600_texture {
- struct u_resource b;
- unsigned long offset[PIPE_MAX_TEXTURE_LEVELS];
- unsigned long pitch[PIPE_MAX_TEXTURE_LEVELS];
- unsigned long stride[PIPE_MAX_TEXTURE_LEVELS];
- unsigned long layer_size[PIPE_MAX_TEXTURE_LEVELS];
- unsigned long stride_override;
- unsigned long size;
- struct pipe_resource *buffer;
-};
-
-struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
- const struct pipe_resource *templ);
-unsigned long r600_texture_get_offset(struct r600_texture *rtex, unsigned level, unsigned zslice, unsigned face);
-struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
- const struct pipe_resource *base,
- struct winsys_handle *whandle);
-void r600_init_screen_texture_functions(struct pipe_screen *screen);
-
-/* This should be implemented by winsys. */
-boolean r600_buffer_get_handle(struct radeon *rw,
- struct pipe_resource *buf,
- struct winsys_handle *whandle);
-
-
-#endif
diff --git a/src/gallium/drivers/r600/r600d.h b/src/gallium/drivers/r600/r600d.h
index 44834984c6..53388f822e 100644
--- a/src/gallium/drivers/r600/r600d.h
+++ b/src/gallium/drivers/r600/r600d.h
@@ -26,6 +26,8 @@
#ifndef R600D_H
#define R600D_H
+#define R600_TEXEL_PITCH_ALIGNMENT_MASK 0x7
+
#define PKT3_NOP 0x10
#define PKT3_INDIRECT_BUFFER_END 0x17
#define PKT3_SET_PREDICATION 0x20
@@ -207,12 +209,24 @@
#define S_0280A0_NUMBER_TYPE(x) (((x) & 0x7) << 12)
#define G_0280A0_NUMBER_TYPE(x) (((x) >> 12) & 0x7)
#define C_0280A0_NUMBER_TYPE 0xFFFF8FFF
+#define V_0280A0_NUMBER_UNORM 0x00000000
+#define V_0280A0_NUMBER_SNORM 0x00000001
+#define V_0280A0_NUMBER_USCALED 0x00000002
+#define V_0280A0_NUMBER_SSCALED 0x00000003
+#define V_0280A0_NUMBER_UINT 0x00000004
+#define V_0280A0_NUMBER_SINT 0x00000005
+#define V_0280A0_NUMBER_SRGB 0x00000006
+#define V_0280A0_NUMBER_FLOAT 0x00000007
#define S_0280A0_READ_SIZE(x) (((x) & 0x1) << 15)
#define G_0280A0_READ_SIZE(x) (((x) >> 15) & 0x1)
#define C_0280A0_READ_SIZE 0xFFFF7FFF
#define S_0280A0_COMP_SWAP(x) (((x) & 0x3) << 16)
#define G_0280A0_COMP_SWAP(x) (((x) >> 16) & 0x3)
#define C_0280A0_COMP_SWAP 0xFFFCFFFF
+#define V_0280A0_SWAP_STD 0x00000000
+#define V_0280A0_SWAP_ALT 0x00000001
+#define V_0280A0_SWAP_STD_REV 0x00000002
+#define V_0280A0_SWAP_ALT_REV 0x00000003
#define S_0280A0_TILE_MODE(x) (((x) & 0x3) << 18)
#define G_0280A0_TILE_MODE(x) (((x) >> 18) & 0x3)
#define C_0280A0_TILE_MODE 0xFFF3FFFF
@@ -247,6 +261,16 @@
#define S_028060_SLICE_TILE_MAX(x) (((x) & 0xFFFFF) << 10)
#define G_028060_SLICE_TILE_MAX(x) (((x) >> 10) & 0xFFFFF)
#define C_028060_SLICE_TILE_MAX 0xC00003FF
+#define R_028410_SX_ALPHA_TEST_CONTROL 0x028410
+#define S_028410_ALPHA_FUNC(x) (((x) & 0x7) << 0)
+#define G_028410_ALPHA_FUNC(x) (((x) >> 0) & 0x7)
+#define C_028410_ALPHA_FUNC 0xFFFFFFF8
+#define S_028410_ALPHA_TEST_ENABLE(x) (((x) & 0x1) << 3)
+#define G_028410_ALPHA_TEST_ENABLE(x) (((x) >> 3) & 0x1)
+#define C_028410_ALPHA_TEST_ENABLE 0xFFFFFFF7
+#define S_028410_ALPHA_TEST_BYPASS(x) (((x) & 0x1) << 8)
+#define G_028410_ALPHA_TEST_BYPASS(x) (((x) >> 8) & 0x1)
+#define C_028410_ALPHA_TEST_BYPASS 0xFFFFFEFF
#define R_028800_DB_DEPTH_CONTROL 0x028800
#define S_028800_STENCIL_ENABLE(x) (((x) & 0x1) << 0)
#define G_028800_STENCIL_ENABLE(x) (((x) >> 0) & 0x1)
@@ -266,9 +290,25 @@
#define S_028800_STENCILFUNC(x) (((x) & 0x7) << 8)
#define G_028800_STENCILFUNC(x) (((x) >> 8) & 0x7)
#define C_028800_STENCILFUNC 0xFFFFF8FF
+#define V_028800_STENCILFUNC_NEVER 0x00000000
+#define V_028800_STENCILFUNC_LESS 0x00000001
+#define V_028800_STENCILFUNC_EQUAL 0x00000002
+#define V_028800_STENCILFUNC_LEQUAL 0x00000003
+#define V_028800_STENCILFUNC_GREATER 0x00000004
+#define V_028800_STENCILFUNC_NOTEQUAL 0x00000005
+#define V_028800_STENCILFUNC_GEQUAL 0x00000006
+#define V_028800_STENCILFUNC_ALWAYS 0x00000007
#define S_028800_STENCILFAIL(x) (((x) & 0x7) << 11)
#define G_028800_STENCILFAIL(x) (((x) >> 11) & 0x7)
#define C_028800_STENCILFAIL 0xFFFFC7FF
+#define V_028800_STENCIL_KEEP 0x00000000
+#define V_028800_STENCIL_ZERO 0x00000001
+#define V_028800_STENCIL_REPLACE 0x00000002
+#define V_028800_STENCIL_INCR 0x00000003
+#define V_028800_STENCIL_DECR 0x00000004
+#define V_028800_STENCIL_INVERT 0x00000005
+#define V_028800_STENCIL_INCR_WRAP 0x00000006
+#define V_028800_STENCIL_DECR_WRAP 0x00000007
#define S_028800_STENCILZPASS(x) (((x) & 0x7) << 14)
#define G_028800_STENCILZPASS(x) (((x) >> 14) & 0x7)
#define C_028800_STENCILZPASS 0xFFFE3FFF
@@ -287,6 +327,86 @@
#define S_028800_STENCILZFAIL_BF(x) (((x) & 0x7) << 29)
#define G_028800_STENCILZFAIL_BF(x) (((x) >> 29) & 0x7)
#define C_028800_STENCILZFAIL_BF 0x1FFFFFFF
+#define R_028808_CB_COLOR_CONTROL 0x028808
+#define S_028808_FOG_ENABLE(x) (((x) & 0x1) << 0)
+#define G_028808_FOG_ENABLE(x) (((x) >> 0) & 0x1)
+#define C_028808_FOG_ENABLE 0xFFFFFFFE
+#define S_028808_MULTIWRITE_ENABLE(x) (((x) & 0x1) << 1)
+#define G_028808_MULTIWRITE_ENABLE(x) (((x) >> 1) & 0x1)
+#define C_028808_MULTIWRITE_ENABLE 0xFFFFFFFD
+#define S_028808_DITHER_ENABLE(x) (((x) & 0x1) << 2)
+#define G_028808_DITHER_ENABLE(x) (((x) >> 2) & 0x1)
+#define C_028808_DITHER_ENABLE 0xFFFFFFFB
+#define S_028808_DEGAMMA_ENABLE(x) (((x) & 0x1) << 3)
+#define G_028808_DEGAMMA_ENABLE(x) (((x) >> 3) & 0x1)
+#define C_028808_DEGAMMA_ENABLE 0xFFFFFFF7
+#define S_028808_SPECIAL_OP(x) (((x) & 0x7) << 4)
+#define G_028808_SPECIAL_OP(x) (((x) >> 4) & 0x7)
+#define C_028808_SPECIAL_OP 0xFFFFFF8F
+#define S_028808_PER_MRT_BLEND(x) (((x) & 0x1) << 7)
+#define G_028808_PER_MRT_BLEND(x) (((x) >> 7) & 0x1)
+#define C_028808_PER_MRT_BLEND 0xFFFFFF7F
+#define S_028808_TARGET_BLEND_ENABLE(x) (((x) & 0xFF) << 8)
+#define G_028808_TARGET_BLEND_ENABLE(x) (((x) >> 8) & 0xFF)
+#define C_028808_TARGET_BLEND_ENABLE 0xFFFF00FF
+#define S_028808_ROP3(x) (((x) & 0xFF) << 16)
+#define G_028808_ROP3(x) (((x) >> 16) & 0xFF)
+#define C_028808_ROP3 0xFF00FFFF
+#define R_028810_PA_CL_CLIP_CNTL 0x028810
+#define S_028810_UCP_ENA_0(x) (((x) & 0x1) << 0)
+#define G_028810_UCP_ENA_0(x) (((x) >> 0) & 0x1)
+#define C_028810_UCP_ENA_0 0xFFFFFFFE
+#define S_028810_UCP_ENA_1(x) (((x) & 0x1) << 1)
+#define G_028810_UCP_ENA_1(x) (((x) >> 1) & 0x1)
+#define C_028810_UCP_ENA_1 0xFFFFFFFD
+#define S_028810_UCP_ENA_2(x) (((x) & 0x1) << 2)
+#define G_028810_UCP_ENA_2(x) (((x) >> 2) & 0x1)
+#define C_028810_UCP_ENA_2 0xFFFFFFFB
+#define S_028810_UCP_ENA_3(x) (((x) & 0x1) << 3)
+#define G_028810_UCP_ENA_3(x) (((x) >> 3) & 0x1)
+#define C_028810_UCP_ENA_3 0xFFFFFFF7
+#define S_028810_UCP_ENA_4(x) (((x) & 0x1) << 4)
+#define G_028810_UCP_ENA_4(x) (((x) >> 4) & 0x1)
+#define C_028810_UCP_ENA_4 0xFFFFFFEF
+#define S_028810_UCP_ENA_5(x) (((x) & 0x1) << 5)
+#define G_028810_UCP_ENA_5(x) (((x) >> 5) & 0x1)
+#define C_028810_UCP_ENA_5 0xFFFFFFDF
+#define S_028810_PS_UCP_Y_SCALE_NEG(x) (((x) & 0x1) << 13)
+#define G_028810_PS_UCP_Y_SCALE_NEG(x) (((x) >> 13) & 0x1)
+#define C_028810_PS_UCP_Y_SCALE_NEG 0xFFFFDFFF
+#define S_028810_PS_UCP_MODE(x) (((x) & 0x3) << 14)
+#define G_028810_PS_UCP_MODE(x) (((x) >> 14) & 0x3)
+#define C_028810_PS_UCP_MODE 0xFFFF3FFF
+#define S_028810_CLIP_DISABLE(x) (((x) & 0x1) << 16)
+#define G_028810_CLIP_DISABLE(x) (((x) >> 16) & 0x1)
+#define C_028810_CLIP_DISABLE 0xFFFEFFFF
+#define S_028810_UCP_CULL_ONLY_ENA(x) (((x) & 0x1) << 17)
+#define G_028810_UCP_CULL_ONLY_ENA(x) (((x) >> 17) & 0x1)
+#define C_028810_UCP_CULL_ONLY_ENA 0xFFFDFFFF
+#define S_028810_BOUNDARY_EDGE_FLAG_ENA(x) (((x) & 0x1) << 18)
+#define G_028810_BOUNDARY_EDGE_FLAG_ENA(x) (((x) >> 18) & 0x1)
+#define C_028810_BOUNDARY_EDGE_FLAG_ENA 0xFFFBFFFF
+#define S_028810_DX_CLIP_SPACE_DEF(x) (((x) & 0x1) << 19)
+#define G_028810_DX_CLIP_SPACE_DEF(x) (((x) >> 19) & 0x1)
+#define C_028810_DX_CLIP_SPACE_DEF 0xFFF7FFFF
+#define S_028810_DIS_CLIP_ERR_DETECT(x) (((x) & 0x1) << 20)
+#define G_028810_DIS_CLIP_ERR_DETECT(x) (((x) >> 20) & 0x1)
+#define C_028810_DIS_CLIP_ERR_DETECT 0xFFEFFFFF
+#define S_028810_VTX_KILL_OR(x) (((x) & 0x1) << 21)
+#define G_028810_VTX_KILL_OR(x) (((x) >> 21) & 0x1)
+#define C_028810_VTX_KILL_OR 0xFFDFFFFF
+#define S_028810_DX_LINEAR_ATTR_CLIP_ENA(x) (((x) & 0x1) << 24)
+#define G_028810_DX_LINEAR_ATTR_CLIP_ENA(x) (((x) >> 24) & 0x1)
+#define C_028810_DX_LINEAR_ATTR_CLIP_ENA 0xFEFFFFFF
+#define S_028810_VTE_VPORT_PROVOKE_DISABLE(x) (((x) & 0x1) << 25)
+#define G_028810_VTE_VPORT_PROVOKE_DISABLE(x) (((x) >> 25) & 0x1)
+#define C_028810_VTE_VPORT_PROVOKE_DISABLE 0xFDFFFFFF
+#define S_028810_ZCLIP_NEAR_DISABLE(x) (((x) & 0x1) << 26)
+#define G_028810_ZCLIP_NEAR_DISABLE(x) (((x) >> 26) & 0x1)
+#define C_028810_ZCLIP_NEAR_DISABLE 0xFBFFFFFF
+#define S_028810_ZCLIP_FAR_DISABLE(x) (((x) & 0x1) << 27)
+#define G_028810_ZCLIP_FAR_DISABLE(x) (((x) >> 27) & 0x1)
+#define C_028810_ZCLIP_FAR_DISABLE 0xF7FFFFFF
#define R_028010_DB_DEPTH_INFO 0x028010
#define S_028010_FORMAT(x) (((x) & 0x7) << 0)
#define G_028010_FORMAT(x) (((x) >> 0) & 0x7)
@@ -314,6 +434,117 @@
#define S_028010_ZRANGE_PRECISION(x) (((x) & 0x1) << 31)
#define G_028010_ZRANGE_PRECISION(x) (((x) >> 31) & 0x1)
#define C_028010_ZRANGE_PRECISION 0x7FFFFFFF
+#define R_028430_DB_STENCILREFMASK 0x028430
+#define S_028430_STENCILREF(x) (((x) & 0xFF) << 0)
+#define G_028430_STENCILREF(x) (((x) >> 0) & 0xFF)
+#define C_028430_STENCILREF 0xFFFFFF00
+#define S_028430_STENCILMASK(x) (((x) & 0xFF) << 8)
+#define G_028430_STENCILMASK(x) (((x) >> 8) & 0xFF)
+#define C_028430_STENCILMASK 0xFFFF00FF
+#define S_028430_STENCILWRITEMASK(x) (((x) & 0xFF) << 16)
+#define G_028430_STENCILWRITEMASK(x) (((x) >> 16) & 0xFF)
+#define C_028430_STENCILWRITEMASK 0xFF00FFFF
+#define R_028434_DB_STENCILREFMASK_BF 0x028434
+#define S_028434_STENCILREF_BF(x) (((x) & 0xFF) << 0)
+#define G_028434_STENCILREF_BF(x) (((x) >> 0) & 0xFF)
+#define C_028434_STENCILREF_BF 0xFFFFFF00
+#define S_028434_STENCILMASK_BF(x) (((x) & 0xFF) << 8)
+#define G_028434_STENCILMASK_BF(x) (((x) >> 8) & 0xFF)
+#define C_028434_STENCILMASK_BF 0xFFFF00FF
+#define S_028434_STENCILWRITEMASK_BF(x) (((x) & 0xFF) << 16)
+#define G_028434_STENCILWRITEMASK_BF(x) (((x) >> 16) & 0xFF)
+#define C_028434_STENCILWRITEMASK_BF 0xFF00FFFF
+#define R_028804_CB_BLEND_CONTROL 0x028804
+#define S_028804_COLOR_SRCBLEND(x) (((x) & 0x1F) << 0)
+#define G_028804_COLOR_SRCBLEND(x) (((x) >> 0) & 0x1F)
+#define C_028804_COLOR_SRCBLEND 0xFFFFFFE0
+#define V_028804_BLEND_ZERO 0x00000000
+#define V_028804_BLEND_ONE 0x00000001
+#define V_028804_BLEND_SRC_COLOR 0x00000002
+#define V_028804_BLEND_ONE_MINUS_SRC_COLOR 0x00000003
+#define V_028804_BLEND_SRC_ALPHA 0x00000004
+#define V_028804_BLEND_ONE_MINUS_SRC_ALPHA 0x00000005
+#define V_028804_BLEND_DST_ALPHA 0x00000006
+#define V_028804_BLEND_ONE_MINUS_DST_ALPHA 0x00000007
+#define V_028804_BLEND_DST_COLOR 0x00000008
+#define V_028804_BLEND_ONE_MINUS_DST_COLOR 0x00000009
+#define V_028804_BLEND_SRC_ALPHA_SATURATE 0x0000000A
+#define V_028804_BLEND_BOTH_SRC_ALPHA 0x0000000B
+#define V_028804_BLEND_BOTH_INV_SRC_ALPHA 0x0000000C
+#define V_028804_BLEND_CONST_COLOR 0x0000000D
+#define V_028804_BLEND_ONE_MINUS_CONST_COLOR 0x0000000E
+#define V_028804_BLEND_SRC1_COLOR 0x0000000F
+#define V_028804_BLEND_INV_SRC1_COLOR 0x00000010
+#define V_028804_BLEND_SRC1_ALPHA 0x00000011
+#define V_028804_BLEND_INV_SRC1_ALPHA 0x00000012
+#define V_028804_BLEND_CONST_ALPHA 0x00000013
+#define V_028804_BLEND_ONE_MINUS_CONST_ALPHA 0x00000014
+#define S_028804_COLOR_COMB_FCN(x) (((x) & 0x7) << 5)
+#define G_028804_COLOR_COMB_FCN(x) (((x) >> 5) & 0x7)
+#define C_028804_COLOR_COMB_FCN 0xFFFFFF1F
+#define V_028804_COMB_DST_PLUS_SRC 0x00000000
+#define V_028804_COMB_SRC_MINUS_DST 0x00000001
+#define V_028804_COMB_MIN_DST_SRC 0x00000002
+#define V_028804_COMB_MAX_DST_SRC 0x00000003
+#define V_028804_COMB_DST_MINUS_SRC 0x00000004
+#define S_028804_COLOR_DESTBLEND(x) (((x) & 0x1F) << 8)
+#define G_028804_COLOR_DESTBLEND(x) (((x) >> 8) & 0x1F)
+#define C_028804_COLOR_DESTBLEND 0xFFFFE0FF
+#define S_028804_OPACITY_WEIGHT(x) (((x) & 0x1) << 13)
+#define G_028804_OPACITY_WEIGHT(x) (((x) >> 13) & 0x1)
+#define C_028804_OPACITY_WEIGHT 0xFFFFDFFF
+#define S_028804_ALPHA_SRCBLEND(x) (((x) & 0x1F) << 16)
+#define G_028804_ALPHA_SRCBLEND(x) (((x) >> 16) & 0x1F)
+#define C_028804_ALPHA_SRCBLEND 0xFFE0FFFF
+#define S_028804_ALPHA_COMB_FCN(x) (((x) & 0x7) << 21)
+#define G_028804_ALPHA_COMB_FCN(x) (((x) >> 21) & 0x7)
+#define C_028804_ALPHA_COMB_FCN 0xFF1FFFFF
+#define S_028804_ALPHA_DESTBLEND(x) (((x) & 0x1F) << 24)
+#define G_028804_ALPHA_DESTBLEND(x) (((x) >> 24) & 0x1F)
+#define C_028804_ALPHA_DESTBLEND 0xE0FFFFFF
+#define S_028804_SEPARATE_ALPHA_BLEND(x) (((x) & 0x1) << 29)
+#define G_028804_SEPARATE_ALPHA_BLEND(x) (((x) >> 29) & 0x1)
+#define C_028804_SEPARATE_ALPHA_BLEND 0xDFFFFFFF
+#define R_028814_PA_SU_SC_MODE_CNTL 0x028814
+#define S_028814_CULL_FRONT(x) (((x) & 0x1) << 0)
+#define G_028814_CULL_FRONT(x) (((x) >> 0) & 0x1)
+#define C_028814_CULL_FRONT 0xFFFFFFFE
+#define S_028814_CULL_BACK(x) (((x) & 0x1) << 1)
+#define G_028814_CULL_BACK(x) (((x) >> 1) & 0x1)
+#define C_028814_CULL_BACK 0xFFFFFFFD
+#define S_028814_FACE(x) (((x) & 0x1) << 2)
+#define G_028814_FACE(x) (((x) >> 2) & 0x1)
+#define C_028814_FACE 0xFFFFFFFB
+#define S_028814_POLY_MODE(x) (((x) & 0x3) << 3)
+#define G_028814_POLY_MODE(x) (((x) >> 3) & 0x3)
+#define C_028814_POLY_MODE 0xFFFFFFE7
+#define S_028814_POLYMODE_FRONT_PTYPE(x) (((x) & 0x7) << 5)
+#define G_028814_POLYMODE_FRONT_PTYPE(x) (((x) >> 5) & 0x7)
+#define C_028814_POLYMODE_FRONT_PTYPE 0xFFFFFF1F
+#define S_028814_POLYMODE_BACK_PTYPE(x) (((x) & 0x7) << 8)
+#define G_028814_POLYMODE_BACK_PTYPE(x) (((x) >> 8) & 0x7)
+#define C_028814_POLYMODE_BACK_PTYPE 0xFFFFF8FF
+#define S_028814_POLY_OFFSET_FRONT_ENABLE(x) (((x) & 0x1) << 11)
+#define G_028814_POLY_OFFSET_FRONT_ENABLE(x) (((x) >> 11) & 0x1)
+#define C_028814_POLY_OFFSET_FRONT_ENABLE 0xFFFFF7FF
+#define S_028814_POLY_OFFSET_BACK_ENABLE(x) (((x) & 0x1) << 12)
+#define G_028814_POLY_OFFSET_BACK_ENABLE(x) (((x) >> 12) & 0x1)
+#define C_028814_POLY_OFFSET_BACK_ENABLE 0xFFFFEFFF
+#define S_028814_POLY_OFFSET_PARA_ENABLE(x) (((x) & 0x1) << 13)
+#define G_028814_POLY_OFFSET_PARA_ENABLE(x) (((x) >> 13) & 0x1)
+#define C_028814_POLY_OFFSET_PARA_ENABLE 0xFFFFDFFF
+#define S_028814_VTX_WINDOW_OFFSET_ENABLE(x) (((x) & 0x1) << 16)
+#define G_028814_VTX_WINDOW_OFFSET_ENABLE(x) (((x) >> 16) & 0x1)
+#define C_028814_VTX_WINDOW_OFFSET_ENABLE 0xFFFEFFFF
+#define S_028814_PROVOKING_VTX_LAST(x) (((x) & 0x1) << 19)
+#define G_028814_PROVOKING_VTX_LAST(x) (((x) >> 19) & 0x1)
+#define C_028814_PROVOKING_VTX_LAST 0xFFF7FFFF
+#define S_028814_PERSP_CORR_DIS(x) (((x) & 0x1) << 20)
+#define G_028814_PERSP_CORR_DIS(x) (((x) >> 20) & 0x1)
+#define C_028814_PERSP_CORR_DIS 0xFFEFFFFF
+#define S_028814_MULTI_PRIM_IB_ENA(x) (((x) & 0x1) << 21)
+#define G_028814_MULTI_PRIM_IB_ENA(x) (((x) >> 21) & 0x1)
+#define C_028814_MULTI_PRIM_IB_ENA 0xFFDFFFFF
#define R_028000_DB_DEPTH_SIZE 0x028000
#define S_028000_PITCH_TILE_MAX(x) (((x) & 0x3FF) << 0)
#define G_028000_PITCH_TILE_MAX(x) (((x) >> 0) & 0x3FF)
@@ -400,6 +631,36 @@
#define S_028D10_IGNORE_SC_ZRANGE(x) (((x) & 0x1) << 17)
#define G_028D10_IGNORE_SC_ZRANGE(x) (((x) >> 17) & 0x1)
#define C_028D10_IGNORE_SC_ZRANGE 0xFFFDFFFF
+#define R_028DF8_PA_SU_POLY_OFFSET_DB_FMT_CNTL 0x028DF8
+#define S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS(x) (((x) & 0xFF) << 0)
+#define G_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS(x) (((x) >> 0) & 0xFF)
+#define C_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS 0xFFFFFF00
+#define S_028DF8_POLY_OFFSET_DB_IS_FLOAT_FMT(x) (((x) & 0x1) << 8)
+#define G_028DF8_POLY_OFFSET_DB_IS_FLOAT_FMT(x) (((x) >> 8) & 0x1)
+#define C_028DF8_POLY_OFFSET_DB_IS_FLOAT_FMT 0xFFFFFEFF
+#define R_028E00_PA_SU_POLY_OFFSET_FRONT_SCALE 0x028E00
+#define S_028E00_SCALE(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_028E00_SCALE(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_028E00_SCALE 0x00000000
+#define R_028E04_PA_SU_POLY_OFFSET_FRONT_OFFSET 0x028E04
+#define S_028E04_OFFSET(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_028E04_OFFSET(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_028E04_OFFSET 0x00000000
+#define R_028E08_PA_SU_POLY_OFFSET_BACK_SCALE 0x028E08
+#define S_028E08_SCALE(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_028E08_SCALE(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_028E08_SCALE 0x00000000
+#define R_028E0C_PA_SU_POLY_OFFSET_BACK_OFFSET 0x028E0C
+#define S_028E0C_OFFSET(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_028E0C_OFFSET(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_028E0C_OFFSET 0x00000000
+#define R_028A00_PA_SU_POINT_SIZE 0x028A00
+#define S_028A00_HEIGHT(x) (((x) & 0xFFFF) << 0)
+#define G_028A00_HEIGHT(x) (((x) >> 0) & 0xFFFF)
+#define C_028A00_HEIGHT 0xFFFF0000
+#define S_028A00_WIDTH(x) (((x) & 0xFFFF) << 16)
+#define G_028A00_WIDTH(x) (((x) >> 16) & 0xFFFF)
+#define C_028A00_WIDTH 0x0000FFFF
#define R_028A40_VGT_GS_MODE 0x028A40
#define S_028A40_MODE(x) (((x) & 0x3) << 0)
#define G_028A40_MODE(x) (((x) >> 0) & 0x3)
@@ -574,6 +835,132 @@
#define S_0287F0_USE_OPAQUE(x) (((x) & 0x1) << 6)
#define G_0287F0_USE_OPAQUE(x) (((x) >> 6) & 0x1)
#define C_0287F0_USE_OPAQUE 0xFFFFFFBF
+#define R_038000_SQ_TEX_RESOURCE_WORD0_0 0x038000
+#define S_038000_DIM(x) (((x) & 0x7) << 0)
+#define G_038000_DIM(x) (((x) >> 0) & 0x7)
+#define C_038000_DIM 0xFFFFFFF8
+#define V_038000_SQ_TEX_DIM_1D 0x00000000
+#define V_038000_SQ_TEX_DIM_2D 0x00000001
+#define V_038000_SQ_TEX_DIM_3D 0x00000002
+#define V_038000_SQ_TEX_DIM_CUBEMAP 0x00000003
+#define V_038000_SQ_TEX_DIM_1D_ARRAY 0x00000004
+#define V_038000_SQ_TEX_DIM_2D_ARRAY 0x00000005
+#define V_038000_SQ_TEX_DIM_2D_MSAA 0x00000006
+#define V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA 0x00000007
+#define S_038000_TILE_MODE(x) (((x) & 0xF) << 3)
+#define G_038000_TILE_MODE(x) (((x) >> 3) & 0xF)
+#define C_038000_TILE_MODE 0xFFFFFF87
+#define S_038000_TILE_TYPE(x) (((x) & 0x1) << 7)
+#define G_038000_TILE_TYPE(x) (((x) >> 7) & 0x1)
+#define C_038000_TILE_TYPE 0xFFFFFF7F
+#define S_038000_PITCH(x) (((x) & 0x7FF) << 8)
+#define G_038000_PITCH(x) (((x) >> 8) & 0x7FF)
+#define C_038000_PITCH 0xFFF800FF
+#define S_038000_TEX_WIDTH(x) (((x) & 0x1FFF) << 19)
+#define G_038000_TEX_WIDTH(x) (((x) >> 19) & 0x1FFF)
+#define C_038000_TEX_WIDTH 0x0007FFFF
+#define R_038004_SQ_TEX_RESOURCE_WORD1_0 0x038004
+#define S_038004_TEX_HEIGHT(x) (((x) & 0x1FFF) << 0)
+#define G_038004_TEX_HEIGHT(x) (((x) >> 0) & 0x1FFF)
+#define C_038004_TEX_HEIGHT 0xFFFFE000
+#define S_038004_TEX_DEPTH(x) (((x) & 0x1FFF) << 13)
+#define G_038004_TEX_DEPTH(x) (((x) >> 13) & 0x1FFF)
+#define C_038004_TEX_DEPTH 0xFC001FFF
+#define S_038004_DATA_FORMAT(x) (((x) & 0x3F) << 26)
+#define G_038004_DATA_FORMAT(x) (((x) >> 26) & 0x3F)
+#define C_038004_DATA_FORMAT 0x03FFFFFF
+#define R_038008_SQ_TEX_RESOURCE_WORD2_0 0x038008
+#define S_038008_BASE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_038008_BASE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_038008_BASE_ADDRESS 0x00000000
+#define R_03800C_SQ_TEX_RESOURCE_WORD3_0 0x03800C
+#define S_03800C_MIP_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_03800C_MIP_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_03800C_MIP_ADDRESS 0x00000000
+#define R_038010_SQ_TEX_RESOURCE_WORD4_0 0x038010
+#define S_038010_FORMAT_COMP_X(x) (((x) & 0x3) << 0)
+#define G_038010_FORMAT_COMP_X(x) (((x) >> 0) & 0x3)
+#define C_038010_FORMAT_COMP_X 0xFFFFFFFC
+#define V_038010_SQ_FORMAT_COMP_UNSIGNED 0x00000000
+#define V_038010_SQ_FORMAT_COMP_SIGNED 0x00000001
+#define V_038010_SQ_FORMAT_COMP_UNSIGNED_BIASED 0x00000002
+#define S_038010_FORMAT_COMP_Y(x) (((x) & 0x3) << 2)
+#define G_038010_FORMAT_COMP_Y(x) (((x) >> 2) & 0x3)
+#define C_038010_FORMAT_COMP_Y 0xFFFFFFF3
+#define S_038010_FORMAT_COMP_Z(x) (((x) & 0x3) << 4)
+#define G_038010_FORMAT_COMP_Z(x) (((x) >> 4) & 0x3)
+#define C_038010_FORMAT_COMP_Z 0xFFFFFFCF
+#define S_038010_FORMAT_COMP_W(x) (((x) & 0x3) << 6)
+#define G_038010_FORMAT_COMP_W(x) (((x) >> 6) & 0x3)
+#define C_038010_FORMAT_COMP_W 0xFFFFFF3F
+#define S_038010_NUM_FORMAT_ALL(x) (((x) & 0x3) << 8)
+#define G_038010_NUM_FORMAT_ALL(x) (((x) >> 8) & 0x3)
+#define C_038010_NUM_FORMAT_ALL 0xFFFFFCFF
+#define V_038010_SQ_NUM_FORMAT_NORM 0x00000000
+#define V_038010_SQ_NUM_FORMAT_INT 0x00000001
+#define V_038010_SQ_NUM_FORMAT_SCALED 0x00000002
+#define S_038010_SRF_MODE_ALL(x) (((x) & 0x1) << 10)
+#define G_038010_SRF_MODE_ALL(x) (((x) >> 10) & 0x1)
+#define C_038010_SRF_MODE_ALL 0xFFFFFBFF
+#define V_038010_SFR_MODE_ZERO_CLAMP_MINUS_ONE 0x00000000
+#define V_038010_SFR_MODE_NO_ZERO 0x00000001
+#define S_038010_FORCE_DEGAMMA(x) (((x) & 0x1) << 11)
+#define G_038010_FORCE_DEGAMMA(x) (((x) >> 11) & 0x1)
+#define C_038010_FORCE_DEGAMMA 0xFFFFF7FF
+#define S_038010_ENDIAN_SWAP(x) (((x) & 0x3) << 12)
+#define G_038010_ENDIAN_SWAP(x) (((x) >> 12) & 0x3)
+#define C_038010_ENDIAN_SWAP 0xFFFFCFFF
+#define S_038010_REQUEST_SIZE(x) (((x) & 0x3) << 14)
+#define G_038010_REQUEST_SIZE(x) (((x) >> 14) & 0x3)
+#define C_038010_REQUEST_SIZE 0xFFFF3FFF
+#define S_038010_DST_SEL_X(x) (((x) & 0x7) << 16)
+#define G_038010_DST_SEL_X(x) (((x) >> 16) & 0x7)
+#define C_038010_DST_SEL_X 0xFFF8FFFF
+#define V_038010_SQ_SEL_X 0x00000000
+#define V_038010_SQ_SEL_Y 0x00000001
+#define V_038010_SQ_SEL_Z 0x00000002
+#define V_038010_SQ_SEL_W 0x00000003
+#define V_038010_SQ_SEL_0 0x00000004
+#define V_038010_SQ_SEL_1 0x00000005
+#define S_038010_DST_SEL_Y(x) (((x) & 0x7) << 19)
+#define G_038010_DST_SEL_Y(x) (((x) >> 19) & 0x7)
+#define C_038010_DST_SEL_Y 0xFFC7FFFF
+#define S_038010_DST_SEL_Z(x) (((x) & 0x7) << 22)
+#define G_038010_DST_SEL_Z(x) (((x) >> 22) & 0x7)
+#define C_038010_DST_SEL_Z 0xFE3FFFFF
+#define S_038010_DST_SEL_W(x) (((x) & 0x7) << 25)
+#define G_038010_DST_SEL_W(x) (((x) >> 25) & 0x7)
+#define C_038010_DST_SEL_W 0xF1FFFFFF
+#define S_038010_BASE_LEVEL(x) (((x) & 0xF) << 28)
+#define G_038010_BASE_LEVEL(x) (((x) >> 28) & 0xF)
+#define C_038010_BASE_LEVEL 0x0FFFFFFF
+#define R_038014_SQ_TEX_RESOURCE_WORD5_0 0x038014
+#define S_038014_LAST_LEVEL(x) (((x) & 0xF) << 0)
+#define G_038014_LAST_LEVEL(x) (((x) >> 0) & 0xF)
+#define C_038014_LAST_LEVEL 0xFFFFFFF0
+#define S_038014_BASE_ARRAY(x) (((x) & 0x1FFF) << 4)
+#define G_038014_BASE_ARRAY(x) (((x) >> 4) & 0x1FFF)
+#define C_038014_BASE_ARRAY 0xFFFE000F
+#define S_038014_LAST_ARRAY(x) (((x) & 0x1FFF) << 17)
+#define G_038014_LAST_ARRAY(x) (((x) >> 17) & 0x1FFF)
+#define C_038014_LAST_ARRAY 0xC001FFFF
+#define R_038018_SQ_TEX_RESOURCE_WORD6_0 0x038018
+#define S_038018_MPEG_CLAMP(x) (((x) & 0x3) << 0)
+#define G_038018_MPEG_CLAMP(x) (((x) >> 0) & 0x3)
+#define C_038018_MPEG_CLAMP 0xFFFFFFFC
+#define S_038018_PERF_MODULATION(x) (((x) & 0x7) << 5)
+#define G_038018_PERF_MODULATION(x) (((x) >> 5) & 0x7)
+#define C_038018_PERF_MODULATION 0xFFFFFF1F
+#define S_038018_INTERLACED(x) (((x) & 0x1) << 8)
+#define G_038018_INTERLACED(x) (((x) >> 8) & 0x1)
+#define C_038018_INTERLACED 0xFFFFFEFF
+#define S_038018_TYPE(x) (((x) & 0x3) << 30)
+#define G_038018_TYPE(x) (((x) >> 30) & 0x3)
+#define C_038018_TYPE 0x3FFFFFFF
+#define V_038010_SQ_TEX_VTX_INVALID_TEXTURE 0x00000000
+#define V_038010_SQ_TEX_VTX_INVALID_BUFFER 0x00000001
+#define V_038010_SQ_TEX_VTX_VALID_TEXTURE 0x00000002
+#define V_038010_SQ_TEX_VTX_VALID_BUFFER 0x00000003
#define R_038008_SQ_VTX_CONSTANT_WORD2_0 0x038008
#define S_038008_BASE_ADDRESS_HI(x) (((x) & 0xFF) << 0)
#define G_038008_BASE_ADDRESS_HI(x) (((x) >> 0) & 0xFF)
@@ -633,6 +1020,113 @@
#define S_038008_ENDIAN_SWAP(x) (((x) & 0x3) << 30)
#define G_038008_ENDIAN_SWAP(x) (((x) >> 30) & 0x3)
#define C_038008_ENDIAN_SWAP 0x3FFFFFFF
+#define R_03C000_SQ_TEX_SAMPLER_WORD0_0 0x03C000
+#define S_03C000_CLAMP_X(x) (((x) & 0x7) << 0)
+#define G_03C000_CLAMP_X(x) (((x) >> 0) & 0x7)
+#define C_03C000_CLAMP_X 0xFFFFFFF8
+#define V_03C000_SQ_TEX_WRAP 0x00000000
+#define V_03C000_SQ_TEX_MIRROR 0x00000001
+#define V_03C000_SQ_TEX_CLAMP_LAST_TEXEL 0x00000002
+#define V_03C000_SQ_TEX_MIRROR_ONCE_LAST_TEXEL 0x00000003
+#define V_03C000_SQ_TEX_CLAMP_HALF_BORDER 0x00000004
+#define V_03C000_SQ_TEX_MIRROR_ONCE_HALF_BORDER 0x00000005
+#define V_03C000_SQ_TEX_CLAMP_BORDER 0x00000006
+#define V_03C000_SQ_TEX_MIRROR_ONCE_BORDER 0x00000007
+#define S_03C000_CLAMP_Y(x) (((x) & 0x7) << 3)
+#define G_03C000_CLAMP_Y(x) (((x) >> 3) & 0x7)
+#define C_03C000_CLAMP_Y 0xFFFFFFC7
+#define S_03C000_CLAMP_Z(x) (((x) & 0x7) << 6)
+#define G_03C000_CLAMP_Z(x) (((x) >> 6) & 0x7)
+#define C_03C000_CLAMP_Z 0xFFFFFE3F
+#define S_03C000_XY_MAG_FILTER(x) (((x) & 0x7) << 9)
+#define G_03C000_XY_MAG_FILTER(x) (((x) >> 9) & 0x7)
+#define C_03C000_XY_MAG_FILTER 0xFFFFF1FF
+#define V_03C000_SQ_TEX_XY_FILTER_POINT 0x00000000
+#define V_03C000_SQ_TEX_XY_FILTER_BILINEAR 0x00000001
+#define V_03C000_SQ_TEX_XY_FILTER_BICUBIC 0x00000002
+#define S_03C000_XY_MIN_FILTER(x) (((x) & 0x7) << 12)
+#define G_03C000_XY_MIN_FILTER(x) (((x) >> 12) & 0x7)
+#define C_03C000_XY_MIN_FILTER 0xFFFF8FFF
+#define S_03C000_Z_FILTER(x) (((x) & 0x3) << 15)
+#define G_03C000_Z_FILTER(x) (((x) >> 15) & 0x3)
+#define C_03C000_Z_FILTER 0xFFFE7FFF
+#define V_03C000_SQ_TEX_Z_FILTER_NONE 0x00000000
+#define V_03C000_SQ_TEX_Z_FILTER_POINT 0x00000001
+#define V_03C000_SQ_TEX_Z_FILTER_LINEAR 0x00000002
+#define S_03C000_MIP_FILTER(x) (((x) & 0x3) << 17)
+#define G_03C000_MIP_FILTER(x) (((x) >> 17) & 0x3)
+#define C_03C000_MIP_FILTER 0xFFF9FFFF
+#define S_03C000_BORDER_COLOR_TYPE(x) (((x) & 0x3) << 22)
+#define G_03C000_BORDER_COLOR_TYPE(x) (((x) >> 22) & 0x3)
+#define C_03C000_BORDER_COLOR_TYPE 0xFF3FFFFF
+#define V_03C000_SQ_TEX_BORDER_COLOR_TRANS_BLACK 0x00000000
+#define V_03C000_SQ_TEX_BORDER_COLOR_OPAQUE_BLACK 0x00000001
+#define V_03C000_SQ_TEX_BORDER_COLOR_OPAQUE_WHITE 0x00000002
+#define V_03C000_SQ_TEX_BORDER_COLOR_REGISTER 0x00000003
+#define S_03C000_POINT_SAMPLING_CLAMP(x) (((x) & 0x1) << 24)
+#define G_03C000_POINT_SAMPLING_CLAMP(x) (((x) >> 24) & 0x1)
+#define C_03C000_POINT_SAMPLING_CLAMP 0xFEFFFFFF
+#define S_03C000_TEX_ARRAY_OVERRIDE(x) (((x) & 0x1) << 25)
+#define G_03C000_TEX_ARRAY_OVERRIDE(x) (((x) >> 25) & 0x1)
+#define C_03C000_TEX_ARRAY_OVERRIDE 0xFDFFFFFF
+#define S_03C000_DEPTH_COMPARE_FUNCTION(x) (((x) & 0x7) << 26)
+#define G_03C000_DEPTH_COMPARE_FUNCTION(x) (((x) >> 26) & 0x7)
+#define C_03C000_DEPTH_COMPARE_FUNCTION 0xE3FFFFFF
+#define V_03C000_SQ_TEX_DEPTH_COMPARE_NEVER 0x00000000
+#define V_03C000_SQ_TEX_DEPTH_COMPARE_LESS 0x00000001
+#define V_03C000_SQ_TEX_DEPTH_COMPARE_EQUAL 0x00000002
+#define V_03C000_SQ_TEX_DEPTH_COMPARE_LESSEQUAL 0x00000003
+#define V_03C000_SQ_TEX_DEPTH_COMPARE_GREATER 0x00000004
+#define V_03C000_SQ_TEX_DEPTH_COMPARE_NOTEQUAL 0x00000005
+#define V_03C000_SQ_TEX_DEPTH_COMPARE_GREATEREQUAL 0x00000006
+#define V_03C000_SQ_TEX_DEPTH_COMPARE_ALWAYS 0x00000007
+#define S_03C000_CHROMA_KEY(x) (((x) & 0x3) << 29)
+#define G_03C000_CHROMA_KEY(x) (((x) >> 29) & 0x3)
+#define C_03C000_CHROMA_KEY 0x9FFFFFFF
+#define V_03C000_SQ_TEX_CHROMA_KEY_DISABLE 0x00000000
+#define V_03C000_SQ_TEX_CHROMA_KEY_KILL 0x00000001
+#define V_03C000_SQ_TEX_CHROMA_KEY_BLEND 0x00000002
+#define S_03C000_LOD_USES_MINOR_AXIS(x) (((x) & 0x1) << 31)
+#define G_03C000_LOD_USES_MINOR_AXIS(x) (((x) >> 31) & 0x1)
+#define C_03C000_LOD_USES_MINOR_AXIS 0x7FFFFFFF
+#define R_03C004_SQ_TEX_SAMPLER_WORD1_0 0x03C004
+#define S_03C004_MIN_LOD(x) (((x) & 0x3FF) << 0)
+#define G_03C004_MIN_LOD(x) (((x) >> 0) & 0x3FF)
+#define C_03C004_MIN_LOD 0xFFFFFC00
+#define S_03C004_MAX_LOD(x) (((x) & 0x3FF) << 10)
+#define G_03C004_MAX_LOD(x) (((x) >> 10) & 0x3FF)
+#define C_03C004_MAX_LOD 0xFFF003FF
+#define S_03C004_LOD_BIAS(x) (((x) & 0xFFF) << 20)
+#define G_03C004_LOD_BIAS(x) (((x) >> 20) & 0xFFF)
+#define C_03C004_LOD_BIAS 0x000FFFFF
+#define R_03C008_SQ_TEX_SAMPLER_WORD2_0 0x03C008
+#define S_03C008_LOD_BIAS_SEC(x) (((x) & 0xFFF) << 0)
+#define G_03C008_LOD_BIAS_SEC(x) (((x) >> 0) & 0xFFF)
+#define C_03C008_LOD_BIAS_SEC 0xFFFFF000
+#define S_03C008_MC_COORD_TRUNCATE(x) (((x) & 0x1) << 12)
+#define G_03C008_MC_COORD_TRUNCATE(x) (((x) >> 12) & 0x1)
+#define C_03C008_MC_COORD_TRUNCATE 0xFFFFEFFF
+#define S_03C008_FORCE_DEGAMMA(x) (((x) & 0x1) << 13)
+#define G_03C008_FORCE_DEGAMMA(x) (((x) >> 13) & 0x1)
+#define C_03C008_FORCE_DEGAMMA 0xFFFFDFFF
+#define S_03C008_HIGH_PRECISION_FILTER(x) (((x) & 0x1) << 14)
+#define G_03C008_HIGH_PRECISION_FILTER(x) (((x) >> 14) & 0x1)
+#define C_03C008_HIGH_PRECISION_FILTER 0xFFFFBFFF
+#define S_03C008_PERF_MIP(x) (((x) & 0x7) << 15)
+#define G_03C008_PERF_MIP(x) (((x) >> 15) & 0x7)
+#define C_03C008_PERF_MIP 0xFFFC7FFF
+#define S_03C008_PERF_Z(x) (((x) & 0x3) << 18)
+#define G_03C008_PERF_Z(x) (((x) >> 18) & 0x3)
+#define C_03C008_PERF_Z 0xFFF3FFFF
+#define S_03C008_FETCH_4(x) (((x) & 0x1) << 26)
+#define G_03C008_FETCH_4(x) (((x) >> 26) & 0x1)
+#define C_03C008_FETCH_4 0xFBFFFFFF
+#define S_03C008_SAMPLE_IS_PCF(x) (((x) & 0x1) << 27)
+#define G_03C008_SAMPLE_IS_PCF(x) (((x) >> 27) & 0x1)
+#define C_03C008_SAMPLE_IS_PCF 0xF7FFFFFF
+#define S_03C008_TYPE(x) (((x) & 0x1) << 31)
+#define G_03C008_TYPE(x) (((x) >> 31) & 0x1)
+#define C_03C008_TYPE 0x7FFFFFFF
#define R_008958_VGT_PRIMITIVE_TYPE 0x008958
#define S_008958_PRIM_TYPE(x) (((x) & 0x3F) << 0)
#define G_008958_PRIM_TYPE(x) (((x) >> 0) & 0x3F)
@@ -666,6 +1160,79 @@
#define V_008958_DI_PT_2D_FILL_RECT_LIST 0x0000001A
#define V_008958_DI_PT_2D_LINE_STRIP 0x0000001B
#define V_008958_DI_PT_2D_TRI_STRIP 0x0000001C
+#define R_02881C_PA_CL_VS_OUT_CNTL 0x02881C
+#define S_02881C_CLIP_DIST_ENA_0(x) (((x) & 0x1) << 0)
+#define G_02881C_CLIP_DIST_ENA_0(x) (((x) >> 0) & 0x1)
+#define C_02881C_CLIP_DIST_ENA_0 0xFFFFFFFE
+#define S_02881C_CLIP_DIST_ENA_1(x) (((x) & 0x1) << 1)
+#define G_02881C_CLIP_DIST_ENA_1(x) (((x) >> 1) & 0x1)
+#define C_02881C_CLIP_DIST_ENA_1 0xFFFFFFFD
+#define S_02881C_CLIP_DIST_ENA_2(x) (((x) & 0x1) << 2)
+#define G_02881C_CLIP_DIST_ENA_2(x) (((x) >> 2) & 0x1)
+#define C_02881C_CLIP_DIST_ENA_2 0xFFFFFFFB
+#define S_02881C_CLIP_DIST_ENA_3(x) (((x) & 0x1) << 3)
+#define G_02881C_CLIP_DIST_ENA_3(x) (((x) >> 3) & 0x1)
+#define C_02881C_CLIP_DIST_ENA_3 0xFFFFFFF7
+#define S_02881C_CLIP_DIST_ENA_4(x) (((x) & 0x1) << 4)
+#define G_02881C_CLIP_DIST_ENA_4(x) (((x) >> 4) & 0x1)
+#define C_02881C_CLIP_DIST_ENA_4 0xFFFFFFEF
+#define S_02881C_CLIP_DIST_ENA_5(x) (((x) & 0x1) << 5)
+#define G_02881C_CLIP_DIST_ENA_5(x) (((x) >> 5) & 0x1)
+#define C_02881C_CLIP_DIST_ENA_5 0xFFFFFFDF
+#define S_02881C_CLIP_DIST_ENA_6(x) (((x) & 0x1) << 6)
+#define G_02881C_CLIP_DIST_ENA_6(x) (((x) >> 6) & 0x1)
+#define C_02881C_CLIP_DIST_ENA_6 0xFFFFFFBF
+#define S_02881C_CLIP_DIST_ENA_7(x) (((x) & 0x1) << 7)
+#define G_02881C_CLIP_DIST_ENA_7(x) (((x) >> 7) & 0x1)
+#define C_02881C_CLIP_DIST_ENA_7 0xFFFFFF7F
+#define S_02881C_CULL_DIST_ENA_0(x) (((x) & 0x1) << 8)
+#define G_02881C_CULL_DIST_ENA_0(x) (((x) >> 8) & 0x1)
+#define C_02881C_CULL_DIST_ENA_0 0xFFFFFEFF
+#define S_02881C_CULL_DIST_ENA_1(x) (((x) & 0x1) << 9)
+#define G_02881C_CULL_DIST_ENA_1(x) (((x) >> 9) & 0x1)
+#define C_02881C_CULL_DIST_ENA_1 0xFFFFFDFF
+#define S_02881C_CULL_DIST_ENA_2(x) (((x) & 0x1) << 10)
+#define G_02881C_CULL_DIST_ENA_2(x) (((x) >> 10) & 0x1)
+#define C_02881C_CULL_DIST_ENA_2 0xFFFFFBFF
+#define S_02881C_CULL_DIST_ENA_3(x) (((x) & 0x1) << 11)
+#define G_02881C_CULL_DIST_ENA_3(x) (((x) >> 11) & 0x1)
+#define C_02881C_CULL_DIST_ENA_3 0xFFFFF7FF
+#define S_02881C_CULL_DIST_ENA_4(x) (((x) & 0x1) << 12)
+#define G_02881C_CULL_DIST_ENA_4(x) (((x) >> 12) & 0x1)
+#define C_02881C_CULL_DIST_ENA_4 0xFFFFEFFF
+#define S_02881C_CULL_DIST_ENA_5(x) (((x) & 0x1) << 13)
+#define G_02881C_CULL_DIST_ENA_5(x) (((x) >> 13) & 0x1)
+#define C_02881C_CULL_DIST_ENA_5 0xFFFFDFFF
+#define S_02881C_CULL_DIST_ENA_6(x) (((x) & 0x1) << 14)
+#define G_02881C_CULL_DIST_ENA_6(x) (((x) >> 14) & 0x1)
+#define C_02881C_CULL_DIST_ENA_6 0xFFFFBFFF
+#define S_02881C_CULL_DIST_ENA_7(x) (((x) & 0x1) << 15)
+#define G_02881C_CULL_DIST_ENA_7(x) (((x) >> 15) & 0x1)
+#define C_02881C_CULL_DIST_ENA_7 0xFFFF7FFF
+#define S_02881C_USE_VTX_POINT_SIZE(x) (((x) & 0x1) << 16)
+#define G_02881C_USE_VTX_POINT_SIZE(x) (((x) >> 16) & 0x1)
+#define C_02881C_USE_VTX_POINT_SIZE 0xFFFEFFFF
+#define S_02881C_USE_VTX_EDGE_FLAG(x) (((x) & 0x1) << 17)
+#define G_02881C_USE_VTX_EDGE_FLAG(x) (((x) >> 17) & 0x1)
+#define C_02881C_USE_VTX_EDGE_FLAG 0xFFFDFFFF
+#define S_02881C_USE_VTX_RENDER_TARGET_INDX(x) (((x) & 0x1) << 18)
+#define G_02881C_USE_VTX_RENDER_TARGET_INDX(x) (((x) >> 18) & 0x1)
+#define C_02881C_USE_VTX_RENDER_TARGET_INDX 0xFFFBFFFF
+#define S_02881C_USE_VTX_VIEWPORT_INDX(x) (((x) & 0x1) << 19)
+#define G_02881C_USE_VTX_VIEWPORT_INDX(x) (((x) >> 19) & 0x1)
+#define C_02881C_USE_VTX_VIEWPORT_INDX 0xFFF7FFFF
+#define S_02881C_USE_VTX_KILL_FLAG(x) (((x) & 0x1) << 20)
+#define G_02881C_USE_VTX_KILL_FLAG(x) (((x) >> 20) & 0x1)
+#define C_02881C_USE_VTX_KILL_FLAG 0xFFEFFFFF
+#define S_02881C_VS_OUT_MISC_VEC_ENA(x) (((x) & 0x1) << 21)
+#define G_02881C_VS_OUT_MISC_VEC_ENA(x) (((x) >> 21) & 0x1)
+#define C_02881C_VS_OUT_MISC_VEC_ENA 0xFFDFFFFF
+#define S_02881C_VS_OUT_CCDIST0_VEC_ENA(x) (((x) & 0x1) << 22)
+#define G_02881C_VS_OUT_CCDIST0_VEC_ENA(x) (((x) >> 22) & 0x1)
+#define C_02881C_VS_OUT_CCDIST0_VEC_ENA 0xFFBFFFFF
+#define S_02881C_VS_OUT_CCDIST1_VEC_ENA(x) (((x) & 0x1) << 23)
+#define G_02881C_VS_OUT_CCDIST1_VEC_ENA(x) (((x) >> 23) & 0x1)
+#define C_02881C_VS_OUT_CCDIST1_VEC_ENA 0xFF7FFFFF
#define R_028868_SQ_PGM_RESOURCES_VS 0x028868
#define S_028868_NUM_GPRS(x) (((x) & 0xFF) << 0)
#define G_028868_NUM_GPRS(x) (((x) >> 0) & 0xFF)
diff --git a/src/gallium/drivers/r600/r700_asm.c b/src/gallium/drivers/r600/r700_asm.c
new file mode 100644
index 0000000000..1ebe20d6ab
--- /dev/null
+++ b/src/gallium/drivers/r600/r700_asm.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010 Jerome Glisse <glisse@freedesktop.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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "r600_asm.h"
+#include "r600_context.h"
+#include "util/u_memory.h"
+#include "r700_sq.h"
+#include <stdio.h>
+
+int r700_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id)
+{
+ unsigned i;
+
+ /* don't replace gpr by pv or ps for destination register */
+ if (alu->is_op3) {
+ bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
+ S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
+ S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
+ S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
+ S_SQ_ALU_WORD0_LAST(alu->last);
+ bc->bytecode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
+ S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
+ S_SQ_ALU_WORD1_OP3_SRC2_SEL(alu->src[2].sel) |
+ S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) |
+ S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) |
+ S_SQ_ALU_WORD1_OP3_ALU_INST(alu->inst) |
+ S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
+ } else {
+ bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
+ S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) |
+ S_SQ_ALU_WORD0_SRC0_NEG(alu->src[0].neg) |
+ S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) |
+ S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) |
+ S_SQ_ALU_WORD0_SRC1_NEG(alu->src[1].neg) |
+ S_SQ_ALU_WORD0_LAST(alu->last);
+ bc->bytecode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) |
+ S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) |
+ S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) |
+ S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) |
+ S_SQ_ALU_WORD1_OP2_WRITE_MASK(alu->dst.write) |
+ S_SQ_ALU_WORD1_OP2_ALU_INST(alu->inst) |
+ S_SQ_ALU_WORD1_BANK_SWIZZLE(0);
+ }
+ if (alu->last) {
+ for (i = 0; i < alu->nliteral; i++) {
+ bc->bytecode[id++] = alu->value[i];
+ }
+ }
+ return 0;
+}
diff --git a/src/gallium/drivers/r600/radeon.h b/src/gallium/drivers/r600/radeon.h
index 3a8405f9b4..8f00a4895a 100644
--- a/src/gallium/drivers/r600/radeon.h
+++ b/src/gallium/drivers/r600/radeon.h
@@ -157,11 +157,42 @@ int radeon_ctx_submit(struct radeon_ctx *ctx);
void radeon_ctx_dump_bof(struct radeon_ctx *ctx, const char *file);
/*
+ * radeon context functions
+ */
+#pragma pack(1)
+struct radeon_cs_reloc {
+ uint32_t handle;
+ uint32_t read_domain;
+ uint32_t write_domain;
+ uint32_t flags;
+};
+#pragma pack()
+
+struct radeon_ctx {
+ int refcount;
+ struct radeon *radeon;
+ u32 *pm4;
+ u32 cpm4;
+ u32 draw_cpm4;
+ unsigned id;
+ unsigned next_id;
+ unsigned nreloc;
+ struct radeon_cs_reloc *reloc;
+ unsigned nbo;
+ struct radeon_bo **bo;
+ unsigned ndraw;
+ struct radeon_draw *cdraw;
+ struct radeon_draw **draw;
+ unsigned nstate;
+ struct radeon_state **state;
+};
+
+/*
* R600/R700
*/
-#define R600_NSTATE 1273
-#define R600_NTYPE 25
+#define R600_NSTATE 1280
+#define R600_NTYPE 32
#define R600_CONFIG 0
#define R600_CONFIG_TYPE 0
@@ -207,12 +238,26 @@ void radeon_ctx_dump_bof(struct radeon_ctx *ctx, const char *file);
#define R600_GS_SAMPLER_BORDER_TYPE 20
#define R600_CB0 1269
#define R600_CB0_TYPE 21
-#define R600_DB 1270
-#define R600_DB_TYPE 22
-#define R600_VGT 1271
-#define R600_VGT_TYPE 23
-#define R600_DRAW 1272
-#define R600_DRAW_TYPE 24
+#define R600_CB1 1270
+#define R600_CB1_TYPE 22
+#define R600_CB2 1271
+#define R600_CB2_TYPE 23
+#define R600_CB3 1272
+#define R600_CB3_TYPE 24
+#define R600_CB4 1273
+#define R600_CB4_TYPE 25
+#define R600_CB5 1274
+#define R600_CB5_TYPE 26
+#define R600_CB6 1275
+#define R600_CB6_TYPE 27
+#define R600_CB7 1276
+#define R600_CB7_TYPE 28
+#define R600_DB 1277
+#define R600_DB_TYPE 29
+#define R600_VGT 1278
+#define R600_VGT_TYPE 30
+#define R600_DRAW 1279
+#define R600_DRAW_TYPE 31
/* R600_CONFIG */
#define R600_CONFIG__SQ_CONFIG 0
#define R600_CONFIG__SQ_GPR_RESOURCE_MGMT_1 1
diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c
index e0dd5cf8c2..3ffda87520 100644
--- a/src/gallium/drivers/rbug/rbug_context.c
+++ b/src/gallium/drivers/rbug/rbug_context.c
@@ -103,10 +103,7 @@ rbug_draw_block_locked(struct rbug_context *rb_pipe, int flag)
}
static void
-rbug_draw_arrays(struct pipe_context *_pipe,
- unsigned prim,
- unsigned start,
- unsigned count)
+rbug_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info)
{
struct rbug_context *rb_pipe = rbug_context(_pipe);
struct pipe_context *pipe = rb_pipe->pipe;
@@ -114,72 +111,7 @@ rbug_draw_arrays(struct pipe_context *_pipe,
pipe_mutex_lock(rb_pipe->draw_mutex);
rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_BEFORE);
- pipe->draw_arrays(pipe,
- prim,
- start,
- count);
-
- rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_AFTER);
- pipe_mutex_unlock(rb_pipe->draw_mutex);
-}
-
-static void
-rbug_draw_elements(struct pipe_context *_pipe,
- struct pipe_resource *_indexResource,
- unsigned indexSize,
- int indexBias,
- unsigned prim,
- unsigned start,
- unsigned count)
-{
- struct rbug_context *rb_pipe = rbug_context(_pipe);
- struct rbug_resource *rb_resource = rbug_resource(_indexResource);
- struct pipe_context *pipe = rb_pipe->pipe;
- struct pipe_resource *indexResource = rb_resource->resource;
-
- pipe_mutex_lock(rb_pipe->draw_mutex);
- rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_BEFORE);
-
- pipe->draw_elements(pipe,
- indexResource,
- indexSize,
- indexBias,
- prim,
- start,
- count);
-
- rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_AFTER);
- pipe_mutex_unlock(rb_pipe->draw_mutex);
-}
-
-static void
-rbug_draw_range_elements(struct pipe_context *_pipe,
- struct pipe_resource *_indexResource,
- unsigned indexSize,
- int indexBias,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count)
-{
- struct rbug_context *rb_pipe = rbug_context(_pipe);
- struct rbug_resource *rb_resource = rbug_resource(_indexResource);
- struct pipe_context *pipe = rb_pipe->pipe;
- struct pipe_resource *indexResource = rb_resource->resource;
-
- pipe_mutex_lock(rb_pipe->draw_mutex);
- rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_BEFORE);
-
- pipe->draw_range_elements(pipe,
- indexResource,
- indexSize,
- indexBias,
- minIndex,
- maxIndex,
- mode,
- start,
- count);
+ pipe->draw_vbo(pipe, info);
rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_AFTER);
pipe_mutex_unlock(rb_pipe->draw_mutex);
@@ -745,6 +677,23 @@ rbug_set_vertex_buffers(struct pipe_context *_pipe,
}
static void
+rbug_set_index_buffer(struct pipe_context *_pipe,
+ const struct pipe_index_buffer *_ib)
+{
+ struct rbug_context *rb_pipe = rbug_context(_pipe);
+ struct pipe_context *pipe = rb_pipe->pipe;
+ struct pipe_index_buffer unwrapped_ib, *ib = NULL;
+
+ if (_ib) {
+ unwrapped_ib = *_ib;
+ unwrapped_ib.buffer = rbug_resource_unwrap(_ib->buffer);
+ ib = &unwrapped_ib;
+ }
+
+ pipe->set_index_buffer(pipe, ib);
+}
+
+static void
rbug_set_sample_mask(struct pipe_context *_pipe,
unsigned sample_mask)
{
@@ -1040,9 +989,7 @@ rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
rb_pipe->base.draw = NULL;
rb_pipe->base.destroy = rbug_destroy;
- rb_pipe->base.draw_arrays = rbug_draw_arrays;
- rb_pipe->base.draw_elements = rbug_draw_elements;
- rb_pipe->base.draw_range_elements = rbug_draw_range_elements;
+ rb_pipe->base.draw_vbo = rbug_draw_vbo;
rb_pipe->base.create_query = rbug_create_query;
rb_pipe->base.destroy_query = rbug_destroy_query;
rb_pipe->base.begin_query = rbug_begin_query;
@@ -1084,6 +1031,7 @@ rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
rb_pipe->base.set_fragment_sampler_views = rbug_set_fragment_sampler_views;
rb_pipe->base.set_vertex_sampler_views = rbug_set_vertex_sampler_views;
rb_pipe->base.set_vertex_buffers = rbug_set_vertex_buffers;
+ rb_pipe->base.set_index_buffer = rbug_set_index_buffer;
rb_pipe->base.set_sample_mask = rbug_set_sample_mask;
rb_pipe->base.resource_copy_region = rbug_resource_copy_region;
rb_pipe->base.clear = rbug_clear;
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index 12ef98aac7..a7c9959b3e 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -282,12 +282,9 @@ softpipe_create_context( struct pipe_screen *screen,
softpipe->pipe.set_viewport_state = softpipe_set_viewport_state;
softpipe->pipe.set_stream_output_buffers = softpipe_set_stream_output_buffers;
softpipe->pipe.set_vertex_buffers = softpipe_set_vertex_buffers;
+ softpipe->pipe.set_index_buffer = softpipe_set_index_buffer;
- 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.draw_vbo = softpipe_draw_vbo;
softpipe->pipe.draw_stream_output = softpipe_draw_stream_output;
softpipe->pipe.clear = softpipe_clear;
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index 53115a827d..9361a3df09 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -82,6 +82,7 @@ struct softpipe_context {
struct pipe_sampler_view *geometry_sampler_views[PIPE_MAX_GEOMETRY_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+ struct pipe_index_buffer index_buffer;
struct {
struct softpipe_resource *buffer[PIPE_MAX_SO_BUFFERS];
int offset[PIPE_MAX_SO_BUFFERS];
@@ -111,6 +112,7 @@ struct softpipe_context {
/** Mapped constant buffers */
const void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
+ unsigned const_buffer_size[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
/** Vertex format */
struct vertex_info vertex_info;
diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
index 9e727c9381..386c8acb8c 100644
--- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
+++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
@@ -111,27 +111,19 @@ softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode)
* When the min/max element indexes aren't known, minIndex should be 0
* and maxIndex should be ~0.
*/
-static void
-softpipe_draw_range_elements_instanced(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count,
- unsigned startInstance,
- unsigned instanceCount)
+void
+softpipe_draw_vbo(struct pipe_context *pipe,
+ const struct pipe_draw_info *info)
{
struct softpipe_context *sp = softpipe_context(pipe);
struct draw_context *draw = sp->draw;
+ void *mapped_indices = NULL;
unsigned i;
if (!softpipe_check_render_cond(sp))
return;
- sp->reduced_api_prim = u_reduced_prim(mode);
+ sp->reduced_api_prim = u_reduced_prim(info->mode);
if (sp->dirty) {
softpipe_update_derived(sp);
@@ -146,31 +138,27 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe,
}
/* Map index buffer, if present */
- if (indexBuffer) {
- void *mapped_indexes = softpipe_resource(indexBuffer)->data;
- draw_set_mapped_element_buffer_range(draw,
- indexSize,
- indexBias,
- minIndex,
- maxIndex,
- mapped_indexes);
- } else {
- /* no index/element buffer */
- draw_set_mapped_element_buffer_range(draw,
- 0, 0,
- start,
- start + count - 1,
- NULL);
+ if (info->indexed && sp->index_buffer.buffer) {
+ char *indices = (char *) softpipe_resource(sp->index_buffer.buffer)->data;
+ mapped_indices = (void *) (indices + sp->index_buffer.offset);
}
+ draw_set_mapped_element_buffer_range(draw, (mapped_indices) ?
+ sp->index_buffer.index_size : 0,
+ info->index_bias,
+ info->min_index,
+ info->max_index,
+ mapped_indices);
+
/* draw! */
- draw_arrays_instanced(draw, mode, start, count, startInstance, instanceCount);
+ draw_arrays_instanced(draw, info->mode, info->start, info->count,
+ info->start_instance, info->instance_count);
/* 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);
}
- if (indexBuffer) {
+ if (mapped_indices) {
draw_set_mapped_element_buffer(draw, 0, 0, NULL);
}
@@ -184,109 +172,3 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe,
/* Note: leave drawing surfaces mapped */
sp->dirty_render_cache = TRUE;
}
-
-
-void
-softpipe_draw_range_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned min_index,
- unsigned max_index,
- unsigned mode, unsigned start, unsigned count)
-{
- softpipe_draw_range_elements_instanced(pipe,
- indexBuffer,
- indexSize,
- indexBias,
- min_index,
- max_index,
- mode,
- start,
- count,
- 0,
- 1);
-}
-
-
-void
-softpipe_draw_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned mode, unsigned start, unsigned count)
-{
- softpipe_draw_range_elements_instanced(pipe,
- indexBuffer,
- indexSize,
- indexBias,
- 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,
- 0,
- 0xffffffff,
- mode,
- start,
- count,
- startInstance,
- instanceCount);
-}
-
-void
-softpipe_draw_elements_instanced(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned mode,
- unsigned start,
- unsigned count,
- unsigned startInstance,
- unsigned instanceCount)
-{
- softpipe_draw_range_elements_instanced(pipe,
- indexBuffer,
- indexSize,
- indexBias,
- 0,
- 0xffffffff,
- mode,
- start,
- count,
- startInstance,
- instanceCount);
-}
-
-void
-softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
- unsigned start, unsigned count)
-{
- softpipe_draw_range_elements_instanced(pipe,
- NULL,
- 0,
- 0,
- 0,
- 0xffffffff,
- mode,
- start,
- count,
- 0,
- 1);
-}
-
diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c
index d240bcbf3b..90f4787d59 100644
--- a/src/gallium/drivers/softpipe/sp_quad_fs.c
+++ b/src/gallium/drivers/softpipe/sp_quad_fs.c
@@ -111,9 +111,10 @@ shade_quads(struct quad_stage *qs,
struct tgsi_exec_machine *machine = softpipe->fs_machine;
unsigned i, nr_quads = 0;
- for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
- machine->Consts[i] = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT][i];
- }
+ tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
+ softpipe->mapped_constants[PIPE_SHADER_FRAGMENT],
+ softpipe->const_buffer_size[PIPE_SHADER_FRAGMENT]);
+
machine->InterpCoefs = quads[0]->coef;
for (i = 0; i < nr; i++) {
diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
index 7d6b86dce0..39d204de8a 100644
--- a/src/gallium/drivers/softpipe/sp_state.h
+++ b/src/gallium/drivers/softpipe/sp_state.h
@@ -221,44 +221,16 @@ void softpipe_set_vertex_buffers(struct pipe_context *,
unsigned count,
const struct pipe_vertex_buffer *);
-
-void softpipe_update_derived( struct softpipe_context *softpipe );
+void softpipe_set_index_buffer(struct pipe_context *,
+ const struct pipe_index_buffer *);
-void softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
- unsigned start, unsigned count);
-
-void softpipe_draw_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned mode, unsigned start, unsigned count);
-void
-softpipe_draw_range_elements(struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned min_index,
- unsigned max_index,
- unsigned mode, unsigned start, unsigned count);
+void softpipe_update_derived( struct softpipe_context *softpipe );
-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_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned mode,
- unsigned start,
- unsigned count,
- unsigned startInstance,
- unsigned instanceCount);
+softpipe_draw_vbo(struct pipe_context *pipe,
+ const struct pipe_draw_info *info);
void softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode);
diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c
index 3fbf1f2578..ded242d3dc 100644
--- a/src/gallium/drivers/softpipe/sp_state_fs.c
+++ b/src/gallium/drivers/softpipe/sp_state_fs.c
@@ -195,6 +195,8 @@ softpipe_set_constant_buffer(struct pipe_context *pipe,
}
softpipe->mapped_constants[shader][index] = data;
+ softpipe->const_buffer_size[shader][index] = size;
+
softpipe->dirty |= SP_NEW_CONSTANTS;
}
diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c
index 462f4d2655..880a7c7cd2 100644
--- a/src/gallium/drivers/softpipe/sp_state_vertex.c
+++ b/src/gallium/drivers/softpipe/sp_state_vertex.c
@@ -88,3 +88,17 @@ softpipe_set_vertex_buffers(struct pipe_context *pipe,
draw_set_vertex_buffers(softpipe->draw, count, buffers);
}
+
+void
+softpipe_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ if (ib)
+ memcpy(&softpipe->index_buffer, ib, sizeof(softpipe->index_buffer));
+ else
+ memset(&softpipe->index_buffer, 0, sizeof(softpipe->index_buffer));
+
+ /* TODO make this more like a state */
+}
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index 9a46de643f..67a7614c8a 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -190,6 +190,7 @@ struct svga_state
struct svga_vertex_shader *vs;
struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS];
+ struct pipe_index_buffer ib;
struct pipe_resource *cb[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c
index 58e930d983..de08bc5e56 100644
--- a/src/gallium/drivers/svga/svga_pipe_draw.c
+++ b/src/gallium/drivers/svga/svga_pipe_draw.c
@@ -227,31 +227,30 @@ svga_draw_range_elements( struct pipe_context *pipe,
static void
-svga_draw_elements( struct pipe_context *pipe,
- struct pipe_resource *index_buffer,
- unsigned index_size, int index_bias,
- unsigned prim, unsigned start, unsigned count)
+svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
- svga_draw_range_elements( pipe, index_buffer,
- index_size, index_bias,
- 0, 0xffffffff,
- prim, start, count );
-}
+ struct svga_context *svga = svga_context(pipe);
-static void
-svga_draw_arrays( struct pipe_context *pipe,
- unsigned prim, unsigned start, unsigned count)
-{
- svga_draw_range_elements(pipe, NULL, 0, 0,
- start, start + count - 1,
- prim,
- start, count);
+ if (info->indexed && svga->curr.ib.buffer) {
+ unsigned offset;
+
+ assert(svga->curr.ib.offset % svga->curr.ib.index_size == 0);
+ offset = svga->curr.ib.offset / svga->curr.ib.index_size;
+
+ svga_draw_range_elements(pipe, svga->curr.ib.buffer,
+ svga->curr.ib.index_size, info->index_bias,
+ info->min_index, info->max_index,
+ info->mode, info->start + offset, info->count);
+ }
+ else {
+ svga_draw_range_elements(pipe, NULL, 0, 0,
+ info->min_index, info->max_index,
+ info->mode, info->start, info->count);
+ }
}
void svga_init_draw_functions( struct svga_context *svga )
{
- svga->pipe.draw_arrays = svga_draw_arrays;
- svga->pipe.draw_elements = svga_draw_elements;
- svga->pipe.draw_range_elements = svga_draw_range_elements;
+ svga->pipe.draw_vbo = svga_draw_vbo;
}
diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c
index 23808ad08e..86c79459f3 100644
--- a/src/gallium/drivers/svga/svga_pipe_vertex.c
+++ b/src/gallium/drivers/svga/svga_pipe_vertex.c
@@ -66,6 +66,24 @@ static void svga_set_vertex_buffers(struct pipe_context *pipe,
}
+static void svga_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct svga_context *svga = svga_context(pipe);
+
+ if (ib) {
+ pipe_resource_reference(&svga->curr.ib.buffer, ib->buffer);
+ memcpy(&svga->curr.ib, ib, sizeof(svga->curr.ib));
+ }
+ else {
+ pipe_resource_reference(&svga->curr.ib.buffer, NULL);
+ memset(&svga->curr.ib, 0, sizeof(svga->curr.ib));
+ }
+
+ /* TODO make this more like a state */
+}
+
+
static void *
svga_create_vertex_elements_state(struct pipe_context *pipe,
unsigned count,
@@ -109,6 +127,7 @@ void svga_cleanup_vertex_state( struct svga_context *svga )
void svga_init_vertex_functions( struct svga_context *svga )
{
svga->pipe.set_vertex_buffers = svga_set_vertex_buffers;
+ svga->pipe.set_index_buffer = svga_set_index_buffer;
svga->pipe.create_vertex_elements_state = svga_create_vertex_elements_state;
svga->pipe.bind_vertex_elements_state = svga_bind_vertex_elements_state;
svga->pipe.delete_vertex_elements_state = svga_delete_vertex_elements_state;
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index 55dd6cf883..84e5a6a824 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -83,85 +83,26 @@ trace_surface_unwrap(struct trace_context *tr_ctx,
static INLINE void
-trace_context_draw_arrays(struct pipe_context *_pipe,
- unsigned mode, unsigned start, unsigned count)
+trace_context_draw_vbo(struct pipe_context *_pipe,
+ const struct pipe_draw_info *info)
{
struct trace_context *tr_ctx = trace_context(_pipe);
struct pipe_context *pipe = tr_ctx->pipe;
- trace_dump_call_begin("pipe_context", "draw_arrays");
+ trace_dump_call_begin("pipe_context", "draw_vbo");
- trace_dump_arg(ptr, pipe);
- trace_dump_arg(uint, mode);
- trace_dump_arg(uint, start);
- trace_dump_arg(uint, count);
-
- pipe->draw_arrays(pipe, mode, start, count);
-
- trace_dump_call_end();
-}
-
-
-static INLINE void
-trace_context_draw_elements(struct pipe_context *_pipe,
- struct pipe_resource *_indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned mode, unsigned start, unsigned count)
-{
- struct trace_context *tr_ctx = trace_context(_pipe);
- struct trace_resource *tr_buf = trace_resource(_indexBuffer);
- struct pipe_context *pipe = tr_ctx->pipe;
- struct pipe_resource *indexBuffer = tr_buf->resource;
-
- trace_dump_call_begin("pipe_context", "draw_elements");
-
- trace_dump_arg(ptr, pipe);
- trace_dump_arg(ptr, indexBuffer);
- trace_dump_arg(uint, indexSize);
- trace_dump_arg(int, indexBias);
- trace_dump_arg(uint, mode);
- trace_dump_arg(uint, start);
- trace_dump_arg(uint, count);
-
- pipe->draw_elements(pipe, indexBuffer, indexSize, indexBias,
- mode, start, count);
-
- trace_dump_call_end();
-}
-
-
-static INLINE void
-trace_context_draw_range_elements(struct pipe_context *_pipe,
- struct pipe_resource *_indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count)
-{
- struct trace_context *tr_ctx = trace_context(_pipe);
- struct trace_resource *tr_buf = trace_resource(_indexBuffer);
- struct pipe_context *pipe = tr_ctx->pipe;
- struct pipe_resource *indexBuffer = tr_buf->resource;
-
- trace_dump_call_begin("pipe_context", "draw_range_elements");
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(bool, info->indexed);
+ trace_dump_arg(uint, info->mode);
+ trace_dump_arg(uint, info->start);
+ trace_dump_arg(uint, info->count);
+ trace_dump_arg(uint, info->start_instance);
+ trace_dump_arg(uint, info->instance_count);
+ trace_dump_arg(int, info->index_bias);
+ trace_dump_arg(uint, info->min_index);
+ trace_dump_arg(uint, info->max_index);
- trace_dump_arg(ptr, pipe);
- trace_dump_arg(ptr, indexBuffer);
- trace_dump_arg(uint, indexSize);
- trace_dump_arg(int, indexBias);
- trace_dump_arg(uint, minIndex);
- trace_dump_arg(uint, maxIndex);
- trace_dump_arg(uint, mode);
- trace_dump_arg(uint, start);
- trace_dump_arg(uint, count);
-
- pipe->draw_range_elements(pipe,
- indexBuffer, indexSize, indexBias,
- minIndex, maxIndex,
- mode, start, count);
+ pipe->draw_vbo(pipe, info);
trace_dump_call_end();
}
@@ -1045,6 +986,30 @@ trace_context_set_vertex_buffers(struct pipe_context *_pipe,
static INLINE void
+trace_context_set_index_buffer(struct pipe_context *_pipe,
+ const struct pipe_index_buffer *_ib)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ struct pipe_index_buffer unwrapped_ib, *ib = NULL;
+
+ if (_ib) {
+ unwrapped_ib = *_ib;
+ unwrapped_ib.buffer = trace_resource_unwrap(tr_ctx, _ib->buffer);
+ ib = &unwrapped_ib;
+ }
+
+ trace_dump_call_begin("pipe_context", "set_index_buffer");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(index_buffer, ib);
+
+ pipe->set_index_buffer(pipe, ib);
+
+ trace_dump_call_end();
+}
+
+static INLINE void
trace_context_resource_copy_region(struct pipe_context *_pipe,
struct pipe_resource *dst,
struct pipe_subresource subdst,
@@ -1433,9 +1398,7 @@ trace_context_create(struct trace_screen *tr_scr,
tr_ctx->base.screen = &tr_scr->base;
tr_ctx->base.destroy = trace_context_destroy;
- tr_ctx->base.draw_arrays = trace_context_draw_arrays;
- tr_ctx->base.draw_elements = trace_context_draw_elements;
- tr_ctx->base.draw_range_elements = trace_context_draw_range_elements;
+ tr_ctx->base.draw_vbo = trace_context_draw_vbo;
tr_ctx->base.create_query = trace_context_create_query;
tr_ctx->base.destroy_query = trace_context_destroy_query;
tr_ctx->base.begin_query = trace_context_begin_query;
@@ -1477,6 +1440,7 @@ trace_context_create(struct trace_screen *tr_scr,
tr_ctx->base.create_sampler_view = trace_create_sampler_view;
tr_ctx->base.sampler_view_destroy = trace_sampler_view_destroy;
tr_ctx->base.set_vertex_buffers = trace_context_set_vertex_buffers;
+ tr_ctx->base.set_index_buffer = trace_context_set_index_buffer;
tr_ctx->base.resource_copy_region = trace_context_resource_copy_region;
tr_ctx->base.clear = trace_context_clear;
tr_ctx->base.clear_render_target = trace_context_clear_render_target;
diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
index 1727c2a020..bd9a9bfaf1 100644
--- a/src/gallium/drivers/trace/tr_dump_state.c
+++ b/src/gallium/drivers/trace/tr_dump_state.c
@@ -533,6 +533,26 @@ void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state)
}
+void trace_dump_index_buffer(const struct pipe_index_buffer *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_index_buffer");
+
+ trace_dump_member(uint, state, index_size);
+ trace_dump_member(uint, state, offset);
+ trace_dump_member(resource_ptr, state, buffer);
+
+ trace_dump_struct_end();
+}
+
+
void trace_dump_vertex_element(const struct pipe_vertex_element *state)
{
if (!trace_dumping_enabled_locked())
diff --git a/src/gallium/drivers/trace/tr_dump_state.h b/src/gallium/drivers/trace/tr_dump_state.h
index e614e8355e..2e70f4e1c7 100644
--- a/src/gallium/drivers/trace/tr_dump_state.h
+++ b/src/gallium/drivers/trace/tr_dump_state.h
@@ -75,6 +75,8 @@ void trace_dump_transfer(const struct pipe_transfer *state);
void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state);
+void trace_dump_index_buffer(const struct pipe_index_buffer *state);
+
void trace_dump_vertex_element(const struct pipe_vertex_element *state);
diff --git a/src/gallium/include/pipe/p_compiler.h b/src/gallium/include/pipe/p_compiler.h
index 0358c14e24..1fa3ec8300 100644
--- a/src/gallium/include/pipe/p_compiler.h
+++ b/src/gallium/include/pipe/p_compiler.h
@@ -102,6 +102,16 @@ typedef unsigned char boolean;
# endif
#endif
+/* Forced function inlining */
+#ifndef ALWAYS_INLINE
+# ifdef __GNUC__
+# define ALWAYS_INLINE inline __attribute__((always_inline))
+# elif defined(_MSC_VER)
+# define ALWAYS_INLINE __forceinline
+# else
+# define ALWAYS_INLINE INLINE
+# endif
+#endif
/* Function visibility */
#ifndef PUBLIC
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 7ec3d63a3f..0579962ec6 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -61,46 +61,8 @@ struct pipe_context {
* VBO drawing
*/
/*@{*/
- void (*draw_arrays)( struct pipe_context *pipe,
- unsigned mode, unsigned start, unsigned count);
-
- void (*draw_elements)( struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- 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_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- 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
- * module.
- */
- void (*draw_range_elements)( struct pipe_context *pipe,
- struct pipe_resource *indexBuffer,
- unsigned indexSize,
- int indexBias,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count);
+ void (*draw_vbo)( struct pipe_context *pipe,
+ const struct pipe_draw_info *info );
/**
* Draw the stream output buffer at index 0
@@ -249,6 +211,9 @@ struct pipe_context {
unsigned num_buffers,
const struct pipe_vertex_buffer * );
+ void (*set_index_buffer)( struct pipe_context *pipe,
+ const struct pipe_index_buffer * );
+
void (*set_stream_output_buffers)(struct pipe_context *,
struct pipe_resource **buffers,
int *offsets, /*array of offsets
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 301fe2b74f..0f1a44cde4 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -426,6 +426,41 @@ struct pipe_vertex_element
};
+/**
+ * An index buffer. When an index buffer is bound, all indices to vertices
+ * will be looked up in the buffer.
+ */
+struct pipe_index_buffer
+{
+ unsigned index_size; /**< size of an index, in bytes */
+ unsigned offset; /**< offset to start of data in buffer, in bytes */
+ struct pipe_resource *buffer; /**< the actual buffer */
+};
+
+
+/**
+ * Information to describe a draw_vbo call.
+ */
+struct pipe_draw_info
+{
+ boolean indexed; /**< use index buffer */
+
+ unsigned mode; /**< the mode of the primitive */
+ unsigned start; /**< the index of the first vertex */
+ unsigned count; /**< number of vertices */
+
+ unsigned start_instance; /**< first instance id */
+ unsigned instance_count; /**< number of instances */
+
+ /**
+ * For indexed drawing, these fields apply after index lookup.
+ */
+ int index_bias; /**< a bias to be added to each index */
+ unsigned min_index; /**< the min index */
+ unsigned max_index; /**< the max index */
+};
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gallium/state_trackers/dri/common/dri1_helper.c b/src/gallium/state_trackers/dri/common/dri1_helper.c
deleted file mode 100644
index ad6c7d3750..0000000000
--- a/src/gallium/state_trackers/dri/common/dri1_helper.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2009, VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-/*
- * Management of pipe objects (surface / pipe / fences) used by DRI1 and DRISW.
- *
- * Author: Keith Whitwell <keithw@vmware.com>
- * Author: Jakob Bornecrantz <wallbraker@gmail.com>
- */
-
-#include "util/u_inlines.h"
-#include "pipe/p_context.h"
-
-#include "dri_screen.h"
-#include "dri_context.h"
-#include "dri_drawable.h"
-#include "dri1_helper.h"
-
-struct pipe_fence_handle *
-dri1_swap_fences_pop_front(struct dri_drawable *draw)
-{
- struct pipe_screen *screen = dri_screen(draw->sPriv)->base.screen;
- struct pipe_fence_handle *fence = NULL;
-
- if (draw->cur_fences >= draw->desired_fences) {
- screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]);
- screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL);
- --draw->cur_fences;
- draw->tail &= DRI_SWAP_FENCES_MASK;
- }
- return fence;
-}
-
-void
-dri1_swap_fences_push_back(struct dri_drawable *draw,
- struct pipe_fence_handle *fence)
-{
- struct pipe_screen *screen = dri_screen(draw->sPriv)->base.screen;
-
- if (!fence)
- return;
-
- if (draw->cur_fences < DRI_SWAP_FENCES_MAX) {
- draw->cur_fences++;
- screen->fence_reference(screen, &draw->swap_fences[draw->head++],
- fence);
- draw->head &= DRI_SWAP_FENCES_MASK;
- }
-}
-
-void
-dri1_swap_fences_clear(struct dri_drawable *drawable)
-{
- struct pipe_screen *screen = dri_screen(drawable->sPriv)->base.screen;
- struct pipe_fence_handle *fence;
-
- while (drawable->cur_fences) {
- fence = dri1_swap_fences_pop_front(drawable);
- screen->fence_reference(screen, &fence, NULL);
- }
-}
-
-struct pipe_surface *
-dri1_get_pipe_surface(struct dri_drawable *drawable, struct pipe_resource *ptex)
-{
- struct pipe_screen *pipe_screen = dri_screen(drawable->sPriv)->base.screen;
- struct pipe_surface *psurf = drawable->dri1_surface;
-
- if (!psurf || psurf->texture != ptex) {
- pipe_surface_reference(&drawable->dri1_surface, NULL);
-
- drawable->dri1_surface = pipe_screen->get_tex_surface(pipe_screen,
- ptex, 0, 0, 0, 0/* no bind flag???*/);
-
- psurf = drawable->dri1_surface;
- }
-
- return psurf;
-}
-
-void
-dri1_destroy_pipe_surface(struct dri_drawable *drawable)
-{
- pipe_surface_reference(&drawable->dri1_surface, NULL);
-}
-
-struct pipe_context *
-dri1_get_pipe_context(struct dri_screen *screen)
-{
- struct pipe_context *pipe = screen->dri1_pipe;
-
- if (!pipe) {
- screen->dri1_pipe =
- screen->base.screen->context_create(screen->base.screen, NULL);
- pipe = screen->dri1_pipe;
- }
-
- return pipe;
-}
-
-void
-dri1_destroy_pipe_context(struct dri_screen *screen)
-{
- if (screen->dri1_pipe)
- screen->dri1_pipe->destroy(screen->dri1_pipe);
-}
diff --git a/src/gallium/state_trackers/dri/common/dri1_helper.h b/src/gallium/state_trackers/dri/common/dri1_helper.h
deleted file mode 100644
index c98adf2df2..0000000000
--- a/src/gallium/state_trackers/dri/common/dri1_helper.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2009, VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-/*
- * Author: Keith Whitwell <keithw@vmware.com>
- * Author: Jakob Bornecrantz <wallbraker@gmail.com>
- */
-
-#ifndef DRI1_HELPER_H
-#define DRI1_HELPER_H
-
-#include "dri_screen.h"
-#include "dri_context.h"
-#include "dri_drawable.h"
-
-struct pipe_fence_handle *
-dri1_swap_fences_pop_front(struct dri_drawable *draw);
-
-void
-dri1_swap_fences_push_back(struct dri_drawable *draw,
- struct pipe_fence_handle *fence);
-
-void
-dri1_swap_fences_clear(struct dri_drawable *drawable);
-
-struct pipe_surface *
-dri1_get_pipe_surface(struct dri_drawable *drawable, struct pipe_resource *ptex);
-
-void
-dri1_destroy_pipe_surface(struct dri_drawable *drawable);
-
-struct pipe_context *
-dri1_get_pipe_context(struct dri_screen *screen);
-
-void
-dri1_destroy_pipe_context(struct dri_screen *screen);
-
-#endif /* DRI1_HELPER_H */
diff --git a/src/gallium/state_trackers/dri/common/dri_context.h b/src/gallium/state_trackers/dri/common/dri_context.h
index b29e853383..692c49d7cd 100644
--- a/src/gallium/state_trackers/dri/common/dri_context.h
+++ b/src/gallium/state_trackers/dri/common/dri_context.h
@@ -60,6 +60,9 @@ struct dri_context
/* gallium */
struct st_context_iface *st;
+
+ /* hooks filled in by dri2 & drisw */
+ __DRIimage * (*lookup_egl_image)(struct dri_context *ctx, void *handle);
};
static INLINE struct dri_context *
diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.c b/src/gallium/state_trackers/dri/common/dri_drawable.c
index 2bc0faffef..1bdfdccf43 100644
--- a/src/gallium/state_trackers/dri/common/dri_drawable.c
+++ b/src/gallium/state_trackers/dri/common/dri_drawable.c
@@ -32,7 +32,6 @@
#include "dri_screen.h"
#include "dri_context.h"
#include "dri_drawable.h"
-#include "dri1_helper.h"
#include "pipe/p_screen.h"
#include "util/u_format.h"
@@ -68,10 +67,10 @@ dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
new_stamp = (drawable->texture_stamp != drawable->dPriv->lastStamp);
if (new_stamp || new_mask || screen->broken_invalidate) {
- if (new_stamp && screen->update_drawable_info)
- screen->update_drawable_info(drawable);
+ if (new_stamp && drawable->update_drawable_info)
+ drawable->update_drawable_info(drawable);
- screen->allocate_textures(drawable, statts, count);
+ drawable->allocate_textures(drawable, statts, count);
/* add existing textures */
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
@@ -100,10 +99,9 @@ dri_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
{
struct dri_drawable *drawable =
(struct dri_drawable *) stfbi->st_manager_private;
- struct dri_screen *screen = dri_screen(drawable->sPriv);
/* XXX remove this and just set the correct one on the framebuffer */
- screen->flush_frontbuffer(drawable, statt);
+ drawable->flush_frontbuffer(drawable, statt);
return TRUE;
}
@@ -138,8 +136,6 @@ dri_create_buffer(__DRIscreen * sPriv,
drawable->dPriv = dPriv;
dPriv->driverPrivate = (void *)drawable;
- drawable->desired_fences = 2;
-
return GL_TRUE;
fail:
FREE(drawable);
@@ -152,23 +148,19 @@ dri_destroy_buffer(__DRIdrawable * dPriv)
struct dri_drawable *drawable = dri_drawable(dPriv);
int i;
- dri1_swap_fences_clear(drawable);
-
- dri1_destroy_pipe_surface(drawable);
+ pipe_surface_reference(&drawable->drisw_surface, NULL);
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
pipe_resource_reference(&drawable->textures[i], NULL);
- drawable->desired_fences = 0;
-
FREE(drawable);
}
/**
* Validate the texture at an attachment. Allocate the texture if it does not
- * exist.
+ * exist. Used by the TFP extension.
*/
-void
+static void
dri_drawable_validate_att(struct dri_drawable *drawable,
enum st_attachment_type statt)
{
@@ -189,11 +181,61 @@ dri_drawable_validate_att(struct dri_drawable *drawable,
drawable->texture_stamp = drawable->dPriv->lastStamp - 1;
- /* this calles into the manager */
drawable->base.validate(&drawable->base, statts, count, NULL);
}
/**
+ * These are used for GLX_EXT_texture_from_pixmap
+ */
+static void
+dri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
+ GLint format, __DRIdrawable *dPriv)
+{
+ struct dri_context *ctx = dri_context(pDRICtx);
+ struct dri_drawable *drawable = dri_drawable(dPriv);
+ struct pipe_resource *pt;
+
+ dri_drawable_validate_att(drawable, ST_ATTACHMENT_FRONT_LEFT);
+
+ pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
+
+ if (pt) {
+ enum pipe_format internal_format = pt->format;
+
+ if (format == __DRI_TEXTURE_FORMAT_RGB) {
+ /* only need to cover the formats recognized by dri_fill_st_visual */
+ switch (internal_format) {
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ internal_format = PIPE_FORMAT_B8G8R8X8_UNORM;
+ break;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ internal_format = PIPE_FORMAT_X8R8G8B8_UNORM;
+ break;
+ default:
+ break;
+ }
+ }
+
+ ctx->st->teximage(ctx->st,
+ (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT,
+ 0, internal_format, pt, FALSE);
+ }
+}
+
+static void
+dri_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
+ __DRIdrawable *dPriv)
+{
+ dri_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
+}
+
+const __DRItexBufferExtension driTexBufferExtension = {
+ { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
+ dri_set_tex_buffer,
+ dri_set_tex_buffer2,
+};
+
+/**
* Get the format and binding of an attachment.
*/
void
diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.h b/src/gallium/state_trackers/dri/common/dri_drawable.h
index 5fd650ac88..74e662d36c 100644
--- a/src/gallium/state_trackers/dri/common/dri_drawable.h
+++ b/src/gallium/state_trackers/dri/common/dri_drawable.h
@@ -33,13 +33,9 @@
#include "state_tracker/st_api.h"
struct pipe_surface;
-struct pipe_fence_handle;
struct st_framebuffer;
struct dri_context;
-#define DRI_SWAP_FENCES_MAX 8
-#define DRI_SWAP_FENCES_MASK 7
-
struct dri_drawable
{
struct st_framebuffer_iface base;
@@ -57,14 +53,18 @@ struct dri_drawable
struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
unsigned int texture_mask, texture_stamp;
- struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX];
- unsigned int head;
- unsigned int tail;
- unsigned int desired_fences;
- unsigned int cur_fences;
+ /* used only by DRISW */
+ struct pipe_surface *drisw_surface;
+
+ /* hooks filled in by dri2 & drisw */
+ void (*allocate_textures)(struct dri_drawable *drawable,
+ const enum st_attachment_type *statts,
+ unsigned count);
- /* used only by DRI1 */
- struct pipe_surface *dri1_surface;
+ void (*update_drawable_info)(struct dri_drawable *drawable);
+
+ void (*flush_frontbuffer)(struct dri_drawable *drawable,
+ enum st_attachment_type statt);
};
static INLINE struct dri_drawable *
@@ -89,9 +89,7 @@ dri_drawable_get_format(struct dri_drawable *drawable,
enum pipe_format *format,
unsigned *bind);
-void
-dri_drawable_validate_att(struct dri_drawable *drawable,
- enum st_attachment_type statt);
+extern const __DRItexBufferExtension driTexBufferExtension;
#endif
diff --git a/src/gallium/state_trackers/dri/common/dri_screen.c b/src/gallium/state_trackers/dri/common/dri_screen.c
index 25cad8d46c..6ad2c7da4d 100644
--- a/src/gallium/state_trackers/dri/common/dri_screen.c
+++ b/src/gallium/state_trackers/dri/common/dri_screen.c
@@ -30,20 +30,10 @@
*/
#include "utils.h"
-#ifndef __NOT_HAVE_DRM_H
-#include "vblank.h"
-#endif
#include "xmlpool.h"
#include "dri_screen.h"
#include "dri_context.h"
-#include "dri_drawable.h"
-#include "dri1_helper.h"
-#ifndef __NOT_HAVE_DRM_H
-#include "dri2.h"
-#else
-#include "drisw.h"
-#endif
#include "util/u_inlines.h"
#include "pipe/p_screen.h"
@@ -303,11 +293,10 @@ dri_get_egl_image(struct st_manager *smapi,
{
struct dri_context *ctx =
(struct dri_context *)stctxi->st_manager_private;
- struct dri_screen *screen = dri_screen(ctx->sPriv);
__DRIimage *img = NULL;
- if (screen->lookup_egl_image) {
- img = screen->lookup_egl_image(ctx, egl_image);
+ if (ctx->lookup_egl_image) {
+ img = ctx->lookup_egl_image(ctx, egl_image);
}
if (!img)
@@ -355,8 +344,6 @@ dri_destroy_option_cache(struct dri_screen * screen)
void
dri_destroy_screen_helper(struct dri_screen * screen)
{
- dri1_destroy_pipe_context(screen);
-
if (screen->st_api && screen->st_api->destroy)
screen->st_api->destroy(screen->st_api);
@@ -366,7 +353,7 @@ dri_destroy_screen_helper(struct dri_screen * screen)
dri_destroy_option_cache(screen);
}
-static void
+void
dri_destroy_screen(__DRIscreen * sPriv)
{
struct dri_screen *screen = dri_screen(sPriv);
@@ -402,38 +389,4 @@ dri_init_screen_helper(struct dri_screen *screen,
return dri_fill_in_modes(screen, pixel_bits);
}
-/**
- * DRI driver virtual function table.
- *
- * DRI versions differ in their implementation of init_screen and swap_buffers.
- */
-const struct __DriverAPIRec driDriverAPI = {
- .DestroyScreen = dri_destroy_screen,
- .CreateContext = dri_create_context,
- .DestroyContext = dri_destroy_context,
- .CreateBuffer = dri_create_buffer,
- .DestroyBuffer = dri_destroy_buffer,
- .MakeCurrent = dri_make_current,
- .UnbindContext = dri_unbind_context,
-
-#ifndef __NOT_HAVE_DRM_H
-
- .GetSwapInfo = NULL,
- .GetDrawableMSC = NULL,
- .WaitForMSC = NULL,
- .InitScreen2 = dri2_init_screen,
-
- .InitScreen = NULL,
- .SwapBuffers = NULL,
- .CopySubBuffer = NULL,
-
-#else
-
- .InitScreen = drisw_init_screen,
- .SwapBuffers = drisw_swap_buffers,
-
-#endif
-
-};
-
/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/common/dri_screen.h b/src/gallium/state_trackers/dri/common/dri_screen.h
index 087ae8d2a4..53ccce145b 100644
--- a/src/gallium/state_trackers/dri/common/dri_screen.h
+++ b/src/gallium/state_trackers/dri/common/dri_screen.h
@@ -64,22 +64,10 @@ struct dri_screen
int fd;
drmLock *drmLock;
- /* hooks filled in by dri1, dri2 & drisw */
- __DRIimage * (*lookup_egl_image)(struct dri_context *ctx, void *handle);
- void (*allocate_textures)(struct dri_drawable *drawable,
- const enum st_attachment_type *statts,
- unsigned count);
- void (*update_drawable_info)(struct dri_drawable *drawable);
- void (*flush_frontbuffer)(struct dri_drawable *drawable,
- enum st_attachment_type statt);
-
/* gallium */
boolean d_depth_bits_last;
boolean sd_depth_bits_last;
boolean auto_fake_front;
-
- /* used only by DRI1 */
- struct pipe_context *dri1_pipe;
};
/** cast wrapper */
@@ -132,6 +120,9 @@ dri_init_screen_helper(struct dri_screen *screen,
void
dri_destroy_screen_helper(struct dri_screen * screen);
+void
+dri_destroy_screen(__DRIscreen * sPriv);
+
#endif
/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/drm/Makefile b/src/gallium/state_trackers/dri/drm/Makefile
index 94fa61fec7..c717b2bdeb 100644
--- a/src/gallium/state_trackers/dri/drm/Makefile
+++ b/src/gallium/state_trackers/dri/drm/Makefile
@@ -17,7 +17,6 @@ C_SOURCES = \
dri_context.c \
dri_screen.c \
dri_drawable.c \
- dri1_helper.c \
dri2.c
# $(TOP)/src/mesa/drivers/dri/common/utils.c \
diff --git a/src/gallium/state_trackers/dri/drm/SConscript b/src/gallium/state_trackers/dri/drm/SConscript
index 0c279d2236..2a0af65f9b 100644
--- a/src/gallium/state_trackers/dri/drm/SConscript
+++ b/src/gallium/state_trackers/dri/drm/SConscript
@@ -21,7 +21,6 @@ if env['dri']:
source = [ 'dri_context.c',
'dri_drawable.c',
'dri_screen.c',
- 'dri1_helper.c',
'dri2.c',
]
)
diff --git a/src/gallium/state_trackers/dri/drm/dri1_helper.c b/src/gallium/state_trackers/dri/drm/dri1_helper.c
deleted file mode 120000
index c45ebf5c10..0000000000
--- a/src/gallium/state_trackers/dri/drm/dri1_helper.c
+++ /dev/null
@@ -1 +0,0 @@
-../common/dri1_helper.c \ No newline at end of file
diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c
index 5c6573fa69..47005c17e2 100644
--- a/src/gallium/state_trackers/dri/drm/dri2.c
+++ b/src/gallium/state_trackers/dri/drm/dri2.c
@@ -38,9 +38,6 @@
#include "dri_screen.h"
#include "dri_context.h"
#include "dri_drawable.h"
-#include "dri2.h"
-
-#include "GL/internal/dri_interface.h"
/**
* DRI2 flush extension.
@@ -70,86 +67,6 @@ static const __DRI2flushExtension dri2FlushExtension = {
};
/**
- * These are used for GLX_EXT_texture_from_pixmap
- */
-static void
-dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
- GLint format, __DRIdrawable *dPriv)
-{
- struct dri_context *ctx = dri_context(pDRICtx);
- struct dri_drawable *drawable = dri_drawable(dPriv);
- struct pipe_resource *pt;
-
- dri_drawable_validate_att(drawable, ST_ATTACHMENT_FRONT_LEFT);
-
- pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
-
- if (pt) {
- enum pipe_format internal_format = pt->format;
-
- if (format == __DRI_TEXTURE_FORMAT_RGB) {
- /* only need to cover the formats recognized by dri_fill_st_visual */
- switch (internal_format) {
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- internal_format = PIPE_FORMAT_B8G8R8X8_UNORM;
- break;
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- internal_format = PIPE_FORMAT_X8R8G8B8_UNORM;
- break;
- default:
- break;
- }
- }
-
- ctx->st->teximage(ctx->st,
- (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT,
- 0, internal_format, pt, FALSE);
- }
-}
-
-static void
-dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
- __DRIdrawable *dPriv)
-{
- dri2_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
-}
-
-static const __DRItexBufferExtension dri2TexBufferExtension = {
- { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
- dri2_set_tex_buffer,
- dri2_set_tex_buffer2,
-};
-
-/**
- * Get the format and binding of an attachment.
- */
-static INLINE void
-dri2_drawable_get_format(struct dri_drawable *drawable,
- enum st_attachment_type statt,
- enum pipe_format *format,
- unsigned *bind)
-{
- switch (statt) {
- case ST_ATTACHMENT_FRONT_LEFT:
- case ST_ATTACHMENT_BACK_LEFT:
- case ST_ATTACHMENT_FRONT_RIGHT:
- case ST_ATTACHMENT_BACK_RIGHT:
- *format = drawable->stvis.color_format;
- *bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
- break;
- case ST_ATTACHMENT_DEPTH_STENCIL:
- *format = drawable->stvis.depth_stencil_format;
- *bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
- break;
- default:
- *format = PIPE_FORMAT_NONE;
- *bind = 0;
- break;
- }
-}
-
-
-/**
* Retrieve __DRIbuffer from the DRI loader.
*/
static __DRIbuffer *
@@ -179,7 +96,7 @@ dri2_drawable_get_buffers(struct dri_drawable *drawable,
unsigned bind;
int att, bpp;
- dri2_drawable_get_format(drawable, statts[i], &format, &bind);
+ dri_drawable_get_format(drawable, statts[i], &format, &bind);
if (format == PIPE_FORMAT_NONE)
continue;
@@ -321,7 +238,7 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
break;
}
- dri2_drawable_get_format(drawable, statt, &format, &bind);
+ dri_drawable_get_format(drawable, statt, &format, &bind);
if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE)
continue;
@@ -354,7 +271,8 @@ dri2_allocate_textures(struct dri_drawable *drawable,
unsigned num_buffers = count;
buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
- dri2_drawable_process_buffers(drawable, buffers, num_buffers);
+ if (buffers)
+ dri2_drawable_process_buffers(drawable, buffers, num_buffers);
}
static void
@@ -485,7 +403,7 @@ static const __DRIextension *dri_screen_extensions[] = {
&driCopySubBufferExtension.base,
&driSwapControlExtension.base,
&driMediaStreamCounterExtension.base,
- &dri2TexBufferExtension.base,
+ &driTexBufferExtension.base,
&dri2FlushExtension.base,
&dri2ImageExtension.base,
&dri2ConfigQueryExtension.base,
@@ -497,7 +415,7 @@ static const __DRIextension *dri_screen_extensions[] = {
*
* Returns the __GLcontextModes supported by this driver.
*/
-const __DRIconfig **
+static const __DRIconfig **
dri2_init_screen(__DRIscreen * sPriv)
{
const __DRIconfig **configs;
@@ -510,9 +428,6 @@ dri2_init_screen(__DRIscreen * sPriv)
screen->sPriv = sPriv;
screen->fd = sPriv->fd;
- screen->lookup_egl_image = dri2_lookup_egl_image;
- screen->allocate_textures = dri2_allocate_textures;
- screen->flush_frontbuffer = dri2_flush_frontbuffer;
sPriv->private = (void *)screen;
sPriv->extensions = dri_screen_extensions;
@@ -534,6 +449,64 @@ fail:
return NULL;
}
+static boolean
+dri2_create_context(gl_api api, const __GLcontextModes * visual,
+ __DRIcontext * cPriv, void *sharedContextPrivate)
+{
+ struct dri_context *ctx = NULL;
+
+ if (!dri_create_context(api, visual, cPriv, sharedContextPrivate))
+ return FALSE;
+
+ ctx = cPriv->driverPrivate;
+
+ ctx->lookup_egl_image = dri2_lookup_egl_image;
+
+ return TRUE;
+}
+
+static boolean
+dri2_create_buffer(__DRIscreen * sPriv,
+ __DRIdrawable * dPriv,
+ const __GLcontextModes * visual, boolean isPixmap)
+{
+ struct dri_drawable *drawable = NULL;
+
+ if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
+ return FALSE;
+
+ drawable = dPriv->driverPrivate;
+
+ drawable->allocate_textures = dri2_allocate_textures;
+ drawable->flush_frontbuffer = dri2_flush_frontbuffer;
+
+ return TRUE;
+}
+
+/**
+ * DRI driver virtual function table.
+ *
+ * DRI versions differ in their implementation of init_screen and swap_buffers.
+ */
+const struct __DriverAPIRec driDriverAPI = {
+ .InitScreen = NULL,
+ .InitScreen2 = dri2_init_screen,
+ .DestroyScreen = dri_destroy_screen,
+ .CreateContext = dri2_create_context,
+ .DestroyContext = dri_destroy_context,
+ .CreateBuffer = dri2_create_buffer,
+ .DestroyBuffer = dri_destroy_buffer,
+ .MakeCurrent = dri_make_current,
+ .UnbindContext = dri_unbind_context,
+
+ .GetSwapInfo = NULL,
+ .GetDrawableMSC = NULL,
+ .WaitForMSC = NULL,
+
+ .SwapBuffers = NULL,
+ .CopySubBuffer = NULL,
+};
+
/* This is the table of extensions that the loader will dlsym() for. */
PUBLIC const __DRIextension *__driDriverExtensions[] = {
&driCoreExtension.base,
diff --git a/src/gallium/state_trackers/dri/sw/Makefile b/src/gallium/state_trackers/dri/sw/Makefile
index a1dadeba5e..33bc0ed9c9 100644
--- a/src/gallium/state_trackers/dri/sw/Makefile
+++ b/src/gallium/state_trackers/dri/sw/Makefile
@@ -20,7 +20,6 @@ C_SOURCES = \
dri_context.c \
dri_screen.c \
dri_drawable.c \
- dri1_helper.c \
drisw.c
include ../../../Makefile.template
diff --git a/src/gallium/state_trackers/dri/sw/SConscript b/src/gallium/state_trackers/dri/sw/SConscript
index 0c5194d6ed..d2eb66668e 100644
--- a/src/gallium/state_trackers/dri/sw/SConscript
+++ b/src/gallium/state_trackers/dri/sw/SConscript
@@ -21,7 +21,6 @@ if env['dri']:
source = [ 'dri_context.c',
'dri_drawable.c',
'dri_screen.c',
- 'dri1_helper.c',
'drisw.c',
]
)
diff --git a/src/gallium/state_trackers/dri/sw/dri1_helper.c b/src/gallium/state_trackers/dri/sw/dri1_helper.c
deleted file mode 120000
index c45ebf5c10..0000000000
--- a/src/gallium/state_trackers/dri/sw/dri1_helper.c
+++ /dev/null
@@ -1 +0,0 @@
-../common/dri1_helper.c \ No newline at end of file
diff --git a/src/gallium/state_trackers/dri/sw/drisw.c b/src/gallium/state_trackers/dri/sw/drisw.c
index 23e99aa0ad..249ccd7fcf 100644
--- a/src/gallium/state_trackers/dri/sw/drisw.c
+++ b/src/gallium/state_trackers/dri/sw/drisw.c
@@ -43,9 +43,9 @@
#include "dri_screen.h"
#include "dri_context.h"
#include "dri_drawable.h"
-#include "dri1_helper.h"
-#include "drisw.h"
+DEBUG_GET_ONCE_BOOL_OPTION(swrast_no_present, "SWRAST_NO_PRESENT", FALSE);
+static boolean swrast_no_present = FALSE;
static INLINE void
get_drawable_info(__DRIdrawable *dPriv, int *w, int *h)
@@ -87,6 +87,24 @@ drisw_put_image(struct dri_drawable *drawable,
put_image(dPriv, data, width, height);
}
+static struct pipe_surface *
+drisw_get_pipe_surface(struct dri_drawable *drawable, struct pipe_resource *ptex)
+{
+ struct pipe_screen *pipe_screen = dri_screen(drawable->sPriv)->base.screen;
+ struct pipe_surface *psurf = drawable->drisw_surface;
+
+ if (!psurf || psurf->texture != ptex) {
+ pipe_surface_reference(&drawable->drisw_surface, NULL);
+
+ drawable->drisw_surface = pipe_screen->get_tex_surface(pipe_screen,
+ ptex, 0, 0, 0, 0/* no bind flag???*/);
+
+ psurf = drawable->drisw_surface;
+ }
+
+ return psurf;
+}
+
static INLINE void
drisw_present_texture(__DRIdrawable *dPriv,
struct pipe_resource *ptex)
@@ -95,7 +113,10 @@ drisw_present_texture(__DRIdrawable *dPriv,
struct dri_screen *screen = dri_screen(drawable->sPriv);
struct pipe_surface *psurf;
- psurf = dri1_get_pipe_surface(drawable, ptex);
+ if (swrast_no_present)
+ return;
+
+ psurf = drisw_get_pipe_surface(drawable, ptex);
if (!psurf)
return;
@@ -128,7 +149,7 @@ drisw_copy_to_front(__DRIdrawable * dPriv,
* Backend functions for st_framebuffer interface and swap_buffers.
*/
-void
+static void
drisw_swap_buffers(__DRIdrawable *dPriv)
{
struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv);
@@ -170,10 +191,6 @@ drisw_flush_frontbuffer(struct dri_drawable *drawable,
* During fixed-size operation, the function keeps allocating new attachments
* as they are requested. Unused attachments are not removed, not until the
* framebuffer is resized or destroyed.
- *
- * It should be possible for DRI1 and DRISW to share this function, but it
- * seems a better seperation and safer for each DRI version to provide its own
- * function.
*/
static void
drisw_allocate_textures(struct dri_drawable *drawable,
@@ -184,7 +201,7 @@ drisw_allocate_textures(struct dri_drawable *drawable,
struct pipe_resource templ;
unsigned width, height;
boolean resized;
- int i;
+ unsigned i;
width = drawable->dPriv->w;
height = drawable->dPriv->h;
@@ -205,7 +222,7 @@ drisw_allocate_textures(struct dri_drawable *drawable,
templ.depth0 = 1;
templ.last_level = 0;
- for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
+ for (i = 0; i < count; i++) {
enum pipe_format format;
unsigned bind;
@@ -215,7 +232,8 @@ drisw_allocate_textures(struct dri_drawable *drawable,
dri_drawable_get_format(drawable, statts[i], &format, &bind);
- if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL)
+ /* if we don't do any present, no need for display targets */
+ if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL && !swrast_no_present)
bind |= PIPE_BIND_DISPLAY_TARGET;
if (format == PIPE_FORMAT_NONE)
@@ -244,7 +262,7 @@ static struct drisw_loader_funcs drisw_lf = {
.put_image = drisw_put_image
};
-const __DRIconfig **
+static const __DRIconfig **
drisw_init_screen(__DRIscreen * sPriv)
{
const __DRIconfig **configs;
@@ -257,9 +275,8 @@ drisw_init_screen(__DRIscreen * sPriv)
screen->sPriv = sPriv;
screen->fd = -1;
- screen->allocate_textures = drisw_allocate_textures;
- screen->update_drawable_info = drisw_update_drawable_info;
- screen->flush_frontbuffer = drisw_flush_frontbuffer;
+
+ swrast_no_present = debug_get_option_swrast_no_present();
sPriv->private = (void *)screen;
sPriv->extensions = drisw_screen_extensions;
@@ -278,6 +295,43 @@ fail:
return NULL;
}
+static boolean
+drisw_create_buffer(__DRIscreen * sPriv,
+ __DRIdrawable * dPriv,
+ const __GLcontextModes * visual, boolean isPixmap)
+{
+ struct dri_drawable *drawable = NULL;
+
+ if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
+ return FALSE;
+
+ drawable = dPriv->driverPrivate;
+
+ drawable->allocate_textures = drisw_allocate_textures;
+ drawable->update_drawable_info = drisw_update_drawable_info;
+ drawable->flush_frontbuffer = drisw_flush_frontbuffer;
+
+ return TRUE;
+}
+
+/**
+ * DRI driver virtual function table.
+ *
+ * DRI versions differ in their implementation of init_screen and swap_buffers.
+ */
+const struct __DriverAPIRec driDriverAPI = {
+ .InitScreen = drisw_init_screen,
+ .DestroyScreen = dri_destroy_screen,
+ .CreateContext = dri_create_context,
+ .DestroyContext = dri_destroy_context,
+ .CreateBuffer = drisw_create_buffer,
+ .DestroyBuffer = dri_destroy_buffer,
+ .MakeCurrent = dri_make_current,
+ .UnbindContext = dri_unbind_context,
+
+ .SwapBuffers = drisw_swap_buffers,
+};
+
/* This is the table of extensions that the loader will dlsym() for. */
PUBLIC const __DRIextension *__driDriverExtensions[] = {
&driCoreExtension.base,
diff --git a/src/gallium/state_trackers/dri/sw/drisw.h b/src/gallium/state_trackers/dri/sw/drisw.h
deleted file mode 100644
index 6c6c891f35..0000000000
--- a/src/gallium/state_trackers/dri/sw/drisw.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2009, VMware, Inc.
- * All Rights Reserved.
- * Copyright 2010 George Sapountzis <gsapountzis@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#ifndef DRISW_H
-#define DRISW_H
-
-#include "dri_context.h"
-#include "dri_drawable.h"
-
-#include "state_tracker/st_api.h"
-#include "dri_wrapper.h"
-
-const __DRIconfig **
-drisw_init_screen(__DRIscreen * sPriv);
-
-void drisw_swap_buffers(__DRIdrawable * dPriv);
-
-#endif /* DRISW_H */
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
index b6321e6b43..56d575ffe0 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -434,9 +434,11 @@ egl_g3d_free_config(void *conf)
static void
egl_g3d_free_screen(void *scr)
{
+#ifdef EGL_MESA_screen_surface
struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr);
FREE(gscr->native_modes);
FREE(gscr);
+#endif
}
static EGLBoolean
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h
index ed2b0409bb..f33dc91cf9 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.h
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.h
@@ -95,15 +95,19 @@ struct egl_g3d_image {
unsigned zslice;
};
+/* standard typecasts */
+_EGL_DRIVER_STANDARD_TYPECASTS(egl_g3d)
+_EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj)
+
+#ifdef EGL_MESA_screen_surface
+
struct egl_g3d_screen {
_EGLScreen base;
const struct native_connector *native;
const struct native_mode **native_modes;
};
-
-/* standard typecasts */
-_EGL_DRIVER_STANDARD_TYPECASTS(egl_g3d)
_EGL_DRIVER_TYPECAST(egl_g3d_screen, _EGLScreen, obj)
-_EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj)
+
+#endif /* EGL_MESA_screen_surface */
#endif /* _EGL_G3D_H_ */
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
index b1fe30a776..1e13cfcf7e 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
@@ -78,7 +78,7 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
gimg = CALLOC_STRUCT(egl_g3d_image);
if (!gimg) {
- _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
+ _eglError(EGL_BAD_ALLOC, "eglCreateEGLImageKHR");
return NULL;
}
diff --git a/src/gallium/state_trackers/egl/x11/glxinit.c b/src/gallium/state_trackers/egl/x11/glxinit.c
index 809a0987e5..57c6aaff86 100644
--- a/src/gallium/state_trackers/egl/x11/glxinit.c
+++ b/src/gallium/state_trackers/egl/x11/glxinit.c
@@ -10,10 +10,16 @@
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/Xproto.h>
+#include <X11/Xlibint.h>
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
#include <sys/time.h>
+#include "GL/glxproto.h"
+#include "GL/glxtokens.h"
+#include "GL/gl.h" /* for GL types needed by __GLcontextModes */
+#include "GL/internal/glcore.h" /* for __GLcontextModes */
+
#include "glxinit.h"
#ifdef GLX_DIRECT_RENDERING
@@ -55,9 +61,9 @@ static /* const */ XExtensionHooks __glXExtensionHooks = {
NULL, /* error_string */
};
-XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
- __glXExtensionName, &__glXExtensionHooks,
- __GLX_NUMBER_EVENTS, NULL)
+static XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
+ __glXExtensionName, &__glXExtensionHooks,
+ __GLX_NUMBER_EVENTS, NULL)
static GLint
_gl_convert_from_x_visual_type(int visualType)
@@ -73,6 +79,17 @@ _gl_convert_from_x_visual_type(int visualType)
? glx_visual_types[visualType] : GLX_NONE;
}
+static void
+_gl_context_modes_destroy(__GLcontextModes * modes)
+{
+ while (modes != NULL) {
+ __GLcontextModes *const next = modes->next;
+
+ Xfree(modes);
+ modes = next;
+ }
+}
+
static __GLcontextModes *
_gl_context_modes_create(unsigned count, size_t minimum_size)
{
@@ -116,18 +133,7 @@ _gl_context_modes_create(unsigned count, size_t minimum_size)
return base;
}
-_X_HIDDEN void
-_gl_context_modes_destroy(__GLcontextModes * modes)
-{
- while (modes != NULL) {
- __GLcontextModes *const next = modes->next;
-
- Xfree(modes);
- modes = next;
- }
-}
-
-_X_HIDDEN char *
+static char *
__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name)
{
xGLXGenericGetStringReq *req;
@@ -194,10 +200,6 @@ FreeScreenConfigs(__GLXdisplayPrivate * priv)
_gl_context_modes_destroy(psc->configs);
psc->configs = NULL; /* NOTE: just for paranoia */
}
- if (psc->visuals) {
- _gl_context_modes_destroy(psc->visuals);
- psc->visuals = NULL; /* NOTE: just for paranoia */
- }
Xfree((char *) psc->serverGLXexts);
}
XFree((char *) priv->screenConfigs);
@@ -215,14 +217,8 @@ __glXFreeDisplayPrivate(XExtData * extension)
priv = (__GLXdisplayPrivate *) extension->private_data;
FreeScreenConfigs(priv);
- if (priv->serverGLXvendor) {
- Xfree((char *) priv->serverGLXvendor);
- priv->serverGLXvendor = 0x0; /* to protect against double free's */
- }
- if (priv->serverGLXversion) {
+ if (priv->serverGLXversion)
Xfree((char *) priv->serverGLXversion);
- priv->serverGLXversion = 0x0; /* to protect against double free's */
- }
Xfree((char *) priv);
return 0;
@@ -234,6 +230,10 @@ __glXFreeDisplayPrivate(XExtData * extension)
** Query the version of the GLX extension. This procedure works even if
** the client extension is not completely set up.
*/
+
+#define GLX_MAJOR_VERSION 1 /* current version numbers */
+#define GLX_MINOR_VERSION 4
+
static Bool
QueryVersion(Display * dpy, int opcode, int *major, int *minor)
{
@@ -263,7 +263,13 @@ QueryVersion(Display * dpy, int opcode, int *major, int *minor)
return GL_TRUE;
}
-_X_HIDDEN void
+#define __GLX_MIN_CONFIG_PROPS 18
+#define __GLX_MAX_CONFIG_PROPS 500
+#define __GLX_EXT_CONFIG_PROPS 10
+#define __GLX_TOTAL_CONFIG (__GLX_MIN_CONFIG_PROPS + \
+ 2 * __GLX_EXT_CONFIG_PROPS)
+
+static void
__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count,
const INT32 * bp, Bool tagged_only,
Bool fbconfig_style_tags)
@@ -506,35 +512,6 @@ createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
}
static GLboolean
-getVisualConfigs(__GLXscreenConfigs *psc,
- __GLXdisplayPrivate *priv, int screen)
-{
- xGLXGetVisualConfigsReq *req;
- xGLXGetVisualConfigsReply reply;
- Display *dpy = priv->dpy;
-
- LockDisplay(dpy);
-
- 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(__GLXscreenConfigs *psc, __GLXdisplayPrivate *priv, int screen)
{
xGLXGetFBConfigsReq *fb_req;
@@ -581,32 +558,6 @@ getFBConfigs(__GLXscreenConfigs *psc, __GLXdisplayPrivate *priv, int screen)
return psc->configs != NULL;
}
-_X_HIDDEN Bool
-glx_screen_init(__GLXscreenConfigs *psc,
- int screen, __GLXdisplayPrivate * priv)
-{
- /* Initialize per screen dynamic client GLX extensions */
- psc->ext_list_first_time = GL_TRUE;
- psc->scr = screen;
- psc->dpy = priv->dpy;
-
- getVisualConfigs(psc, priv, screen);
- getFBConfigs(psc, priv, screen);
-
- return GL_TRUE;
-}
-
-static __GLXscreenConfigs *
-createIndirectScreen()
-{
- __GLXscreenConfigs *psc;
-
- psc = Xmalloc(sizeof *psc);
- memset(psc, 0, sizeof *psc);
-
- return psc;
-}
-
static GLboolean
AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
{
@@ -630,10 +581,10 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
}
for (i = 0; i < screens; i++) {
- psc = createIndirectScreen();
+ psc = Xcalloc(1, sizeof *psc);
if (!psc)
return GL_FALSE;
- glx_screen_init(psc, i, priv);
+ getFBConfigs(psc, priv, i);
priv->screenConfigs[i] = psc;
}
@@ -682,13 +633,8 @@ __glXInitialize(Display * dpy)
** 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);
Xfree(private);
diff --git a/src/gallium/state_trackers/egl/x11/glxinit.h b/src/gallium/state_trackers/egl/x11/glxinit.h
index 1cc7c460fe..4078aef2fe 100644
--- a/src/gallium/state_trackers/egl/x11/glxinit.h
+++ b/src/gallium/state_trackers/egl/x11/glxinit.h
@@ -2,10 +2,21 @@
#define GLXINIT_INCLUDED
#include <X11/Xlib.h>
-#include "glxclient.h"
+#include <GL/gl.h>
-/* this is used by DRI loaders */
-extern void
-_gl_context_modes_destroy(__GLcontextModes * modes);
+typedef struct {
+ __GLcontextModes *configs;
+ char *serverGLXexts;
+} __GLXscreenConfigs;
+
+typedef struct {
+ Display *dpy;
+ __GLXscreenConfigs **screenConfigs;
+ char *serverGLXversion;
+ int majorOpcode;
+ struct x11_screen *xscr;
+} __GLXdisplayPrivate;
+
+extern __GLXdisplayPrivate *__glXInitialize(Display * dpy);
#endif /* GLXINIT_INCLUDED */
diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.c b/src/gallium/state_trackers/egl/x11/x11_screen.c
index bc6482ab15..c07ebb7ef6 100644
--- a/src/gallium/state_trackers/egl/x11/x11_screen.c
+++ b/src/gallium/state_trackers/egl/x11/x11_screen.c
@@ -39,11 +39,6 @@
#include "glxinit.h"
struct x11_screen {
-#ifdef GLX_DIRECT_RENDERING
- /* dummy base class */
- struct __GLXDRIdisplayRec base;
-#endif
-
Display *dpy;
int number;
@@ -108,7 +103,7 @@ x11_screen_destroy(struct x11_screen *xscr)
#ifdef GLX_DIRECT_RENDERING
/* xscr->glx_dpy will be destroyed with the X display */
if (xscr->glx_dpy)
- xscr->glx_dpy->dri2Display = NULL;
+ xscr->glx_dpy->xscr = NULL;
#endif
if (xscr->visuals)
@@ -231,17 +226,6 @@ x11_screen_get_glx_configs(struct x11_screen *xscr)
}
/**
- * 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;
-}
-
-/**
* Probe the screen for the DRI2 driver name.
*/
const char *
@@ -306,14 +290,14 @@ x11_screen_enable_dri2(struct x11_screen *xscr,
close(fd);
return -1;
}
- if (xscr->glx_dpy->dri2Display) {
+ if (xscr->glx_dpy->xscr) {
_eglLog(_EGL_WARNING,
"display is already managed by another x11 screen");
close(fd);
return -1;
}
- xscr->glx_dpy->dri2Display = (__GLXDRIdisplay *) xscr;
+ xscr->glx_dpy->xscr = xscr;
xscr->dri_invalidate_buffers = invalidate_buffers;
xscr->dri_user_data = user_data;
@@ -428,6 +412,9 @@ x11_context_modes_count(const __GLcontextModes *modes)
return count;
}
+extern void
+dri2InvalidateBuffers(Display *dpy, XID drawable);
+
/**
* This is called from src/glx/dri2.c.
*/
@@ -437,8 +424,8 @@ dri2InvalidateBuffers(Display *dpy, XID drawable)
__GLXdisplayPrivate *priv = __glXInitialize(dpy);
struct x11_screen *xscr = NULL;
- if (priv && priv->dri2Display)
- xscr = (struct x11_screen *) priv->dri2Display;
+ if (priv && priv->xscr)
+ xscr = priv->xscr;
if (!xscr || !xscr->dri_invalidate_buffers)
return;
diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i
index cf0144b5dc..40c4603fb9 100644
--- a/src/gallium/state_trackers/python/p_context.i
+++ b/src/gallium/state_trackers/python/p_context.i
@@ -289,6 +289,20 @@ struct st_context {
$self->vertex_buffers);
}
+ void set_index_buffer(unsigned index_size,
+ unsigned offset,
+ struct pipe_resource *buffer)
+ {
+ struct pipe_index_buffer ib;
+
+ memset(&ib, 0, sizeof(ib));
+ ib.index_size = index_size;
+ ib.offset = offset;
+ ib.buffer = buffer;
+
+ $self->pipe->set_index_buffer($self->pipe, &ib);
+ }
+
void set_vertex_element(unsigned index,
const struct pipe_vertex_element *element)
{
@@ -308,29 +322,12 @@ struct st_context {
*/
void draw_arrays(unsigned mode, unsigned start, unsigned count) {
- $self->pipe->draw_arrays($self->pipe, mode, start, count);
- }
-
- void draw_elements( struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned mode, unsigned start, unsigned count)
- {
- $self->pipe->draw_elements($self->pipe,
- indexBuffer,
- indexSize,
- indexBias,
- mode, start, count);
+ util_draw_arrays($self->pipe, mode, start, count);
}
- void draw_range_elements( struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias,
- unsigned minIndex, unsigned maxIndex,
- unsigned mode, unsigned start, unsigned count)
+ void draw_vbo(const struct pipe_draw_info *info)
{
- $self->pipe->draw_range_elements($self->pipe,
- indexBuffer, indexSize, indexBias,
- minIndex, maxIndex,
- mode, start, count);
+ $self->pipe->draw_vbo($self->pipe, info);
}
void draw_vertices(unsigned prim,
@@ -382,7 +379,7 @@ struct st_context {
pipe->set_vertex_buffers(pipe, 1, &vbuffer);
/* draw */
- pipe->draw_arrays(pipe, prim, 0, num_verts);
+ util_draw_arrays(pipe, prim, 0, num_verts);
cso_restore_vertex_elements($self->cso);
diff --git a/src/gallium/state_trackers/vega/polygon.c b/src/gallium/state_trackers/vega/polygon.c
index e9c8f03137..bc94170eb9 100644
--- a/src/gallium/state_trackers/vega/polygon.c
+++ b/src/gallium/state_trackers/vega/polygon.c
@@ -301,8 +301,7 @@ static void draw_polygon(struct vg_context *ctx,
cso_set_vertex_elements(ctx->cso_context, 1, &velement);
/* draw */
- pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN,
- 0, poly->num_verts);
+ util_draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, (uint) poly->num_verts);
}
void polygon_fill(struct polygon *poly, struct vg_context *ctx)
diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c
index e993ccc9bf..e10ff2f950 100644
--- a/src/gallium/state_trackers/xorg/xorg_driver.c
+++ b/src/gallium/state_trackers/xorg/xorg_driver.c
@@ -472,7 +472,6 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags)
max_height = max < max_height ? max : max_height;
}
- drmModeFreeResources(res);
xf86CrtcSetSizeRange(pScrn, res->min_width,
res->min_height, max_width, max_height);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
@@ -481,6 +480,7 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Min height %d, Max Height %d.\n",
res->min_height, max_height);
+ drmModeFreeResources(res);
}
diff --git a/src/gallium/targets/Makefile.xorg b/src/gallium/targets/Makefile.xorg
index c2d0064978..762c905985 100644
--- a/src/gallium/targets/Makefile.xorg
+++ b/src/gallium/targets/Makefile.xorg
@@ -42,7 +42,7 @@ endif
default: depend $(TOP)/$(LIB_DIR)/gallium $(LIBNAME) $(LIBNAME_STAGING)
$(LIBNAME): $(OBJECTS) Makefile ../Makefile.xorg $(LIBS) $(DRIVER_PIPES)
- $(MKLIB) -noprefix -o $@ $(OBJECTS) $(DRIVER_PIPES) $(GALLIUM_AUXILIARIES) $(DRIVER_LINKS)
+ $(MKLIB) -noprefix -o $@ $(LDFLAGS) $(OBJECTS) $(DRIVER_PIPES) $(GALLIUM_AUXILIARIES) $(DRIVER_LINKS)
depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(SYMLINKS) $(GENERATED_SOURCES)
rm -f depend
diff --git a/src/gallium/targets/dri-i915/Makefile b/src/gallium/targets/dri-i915/Makefile
index e88c3c9f66..9c10d71a4a 100644
--- a/src/gallium/targets/dri-i915/Makefile
+++ b/src/gallium/targets/dri-i915/Makefile
@@ -22,7 +22,7 @@ DRIVER_DEFINES = \
-DGALLIUM_RBUG -DGALLIUM_TRACE -DGALLIUM_GALAHAD -DGALLIUM_SOFTPIPE
ifeq ($(MESA_LLVM),1)
-DRIVER_DEFINS += -DGALLIUM_LLVMPIPE
+DRIVER_DEFINES += -DGALLIUM_LLVMPIPE
endif
include ../Makefile.dri
diff --git a/src/gallium/targets/dri-i965/Makefile b/src/gallium/targets/dri-i965/Makefile
index 3679c075b2..4b50d04255 100644
--- a/src/gallium/targets/dri-i965/Makefile
+++ b/src/gallium/targets/dri-i965/Makefile
@@ -6,10 +6,11 @@ LIBNAME = i965_dri.so
PIPE_DRIVERS = \
$(TOP)/src/gallium/state_trackers/dri/drm/libdridrm.a \
$(TOP)/src/gallium/winsys/i965/drm/libi965drm.a \
- $(TOP)/src/gallium/drivers/trace/libtrace.a \
- $(TOP)/src/gallium/drivers/rbug/librbug.a \
$(TOP)/src/gallium/winsys/sw/wrapper/libwsw.a \
$(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+ $(TOP)/src/gallium/drivers/galahad/libgalahad.a \
+ $(TOP)/src/gallium/drivers/trace/libtrace.a \
+ $(TOP)/src/gallium/drivers/rbug/librbug.a \
$(TOP)/src/gallium/drivers/i965/libi965.a
C_SOURCES = \
@@ -18,7 +19,11 @@ C_SOURCES = \
$(DRIVER_SOURCES)
DRIVER_DEFINES = \
- -DGALLIUM_SOFTPIPE -DGALLIUM_RBUG -DGALLIUM_TRACE
+ -DGALLIUM_RBUG -DGALLIUM_TRACE -DGALLIUM_GALAHAD -DGALLIUM_SOFTPIPE
+
+ifeq ($(MESA_LLVM),1)
+DRIVER_DEFINES += -DGALLIUM_LLVMPIPE
+endif
include ../Makefile.dri
diff --git a/src/gallium/targets/dri-r600/SConscript b/src/gallium/targets/dri-r600/SConscript
index 97c5df01fe..64d6d2a7f6 100644
--- a/src/gallium/targets/dri-r600/SConscript
+++ b/src/gallium/targets/dri-r600/SConscript
@@ -12,7 +12,7 @@ env.Append(CPPDEFINES = ['GALLIUM_RBUG', 'GALLIUM_TRACE'])
env.Prepend(LIBS = [
st_dri,
- r600drm,
+ r600winsys,
r600,
trace,
rbug,
diff --git a/src/gallium/targets/egl/st_GL.c b/src/gallium/targets/egl/st_GL.c
index 676300b0cc..17b7bf9d48 100644
--- a/src/gallium/targets/egl/st_GL.c
+++ b/src/gallium/targets/egl/st_GL.c
@@ -1,4 +1,5 @@
#include "state_tracker/st_gl_api.h"
+#include "state_tracker/st_api.h"
#if FEATURE_GL
PUBLIC struct st_api *
diff --git a/src/gallium/targets/egl/st_GLESv1_CM.c b/src/gallium/targets/egl/st_GLESv1_CM.c
index 0c8de8992f..c1652d5131 100644
--- a/src/gallium/targets/egl/st_GLESv1_CM.c
+++ b/src/gallium/targets/egl/st_GLESv1_CM.c
@@ -1,3 +1,4 @@
+#include "state_tracker/st_api.h"
#include "state_tracker/st_gl_api.h"
PUBLIC struct st_api *
diff --git a/src/gallium/targets/egl/st_GLESv2.c b/src/gallium/targets/egl/st_GLESv2.c
index 87b3e65e23..9c26989008 100644
--- a/src/gallium/targets/egl/st_GLESv2.c
+++ b/src/gallium/targets/egl/st_GLESv2.c
@@ -1,3 +1,4 @@
+#include "state_tracker/st_api.h"
#include "state_tracker/st_gl_api.h"
PUBLIC struct st_api *
diff --git a/src/gallium/tests/graw/SConscript b/src/gallium/tests/graw/SConscript
index 61121732e3..860a17e13e 100644
--- a/src/gallium/tests/graw/SConscript
+++ b/src/gallium/tests/graw/SConscript
@@ -11,6 +11,12 @@ env = env.Clone()
env.Prepend(LIBPATH = [graw.dir])
env.Prepend(LIBS = ['graw'] + gallium)
+if platform in ('freebsd8', 'sunos5'):
+ env.Append(LIBS = ['m'])
+
+if platform == 'freebsd8':
+ env.Append(LIBS = ['pthread'])
+
progs = [
'clear',
'tri',
diff --git a/src/gallium/tests/graw/fs-test.c b/src/gallium/tests/graw/fs-test.c
index dea087357d..53fbb744d8 100644
--- a/src/gallium/tests/graw/fs-test.c
+++ b/src/gallium/tests/graw/fs-test.c
@@ -13,6 +13,7 @@
#include "util/u_debug.h" /* debug_dump_surface_bmp() */
#include "util/u_inlines.h"
#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
#include "util/u_box.h"
static const char *filename = NULL;
@@ -275,7 +276,7 @@ static void draw( void )
float clear_color[4] = {.1,.3,.5,0};
ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
- ctx->draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
+ util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
#if 0
diff --git a/src/gallium/tests/graw/gs-test.c b/src/gallium/tests/graw/gs-test.c
index 3087d446fc..62714900bd 100644
--- a/src/gallium/tests/graw/gs-test.c
+++ b/src/gallium/tests/graw/gs-test.c
@@ -13,6 +13,7 @@
#include "util/u_debug.h" /* debug_dump_surface_bmp() */
#include "util/u_inlines.h"
#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
#include "util/u_box.h"
static const char *filename = NULL;
@@ -336,9 +337,9 @@ static void draw( void )
ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
if (draw_strip)
- ctx->draw_arrays(ctx, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
+ util_draw_arrays(ctx, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
else
- ctx->draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
+ util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
diff --git a/src/gallium/tests/graw/quad-tex.c b/src/gallium/tests/graw/quad-tex.c
index 6a0a2ba295..c50ef12ab5 100644
--- a/src/gallium/tests/graw/quad-tex.c
+++ b/src/gallium/tests/graw/quad-tex.c
@@ -12,6 +12,7 @@
#include "util/u_debug.h" /* debug_dump_surface_bmp() */
#include "util/u_inlines.h"
#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
#include "util/u_box.h"
enum pipe_format formats[] = {
@@ -146,7 +147,7 @@ static void draw( void )
float clear_color[4] = {.5,.5,.5,1};
ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
- ctx->draw_arrays(ctx, PIPE_PRIM_QUADS, 0, 4);
+ util_draw_arrays(ctx, PIPE_PRIM_QUADS, 0, 4);
ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
#if 0
diff --git a/src/gallium/tests/graw/tri-gs.c b/src/gallium/tests/graw/tri-gs.c
index d187505f8d..152ae408eb 100644
--- a/src/gallium/tests/graw/tri-gs.c
+++ b/src/gallium/tests/graw/tri-gs.c
@@ -10,6 +10,7 @@
#include "util/u_debug.h" /* debug_dump_surface_bmp() */
#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
enum pipe_format formats[] = {
PIPE_FORMAT_R8G8B8A8_UNORM,
@@ -161,7 +162,7 @@ static void draw( void )
float clear_color[4] = {1,0,1,1};
ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
- ctx->draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
+ util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
screen->flush_frontbuffer(screen, surf, window);
diff --git a/src/gallium/tests/graw/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c
index 30e205f143..8859f745fd 100644
--- a/src/gallium/tests/graw/tri-instanced.c
+++ b/src/gallium/tests/graw/tri-instanced.c
@@ -13,6 +13,7 @@
#include "util/u_debug.h" /* debug_dump_surface_bmp() */
#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
enum pipe_format formats[] = {
@@ -27,7 +28,6 @@ static const int HEIGHT = 300;
static struct pipe_screen *screen = NULL;
static struct pipe_context *ctx = NULL;
static struct pipe_surface *surf = NULL;
-static struct pipe_resource *indexBuffer = NULL;
static void *window = NULL;
struct vertex {
@@ -105,6 +105,7 @@ static void set_vertices( void )
{
struct pipe_vertex_element ve[3];
struct pipe_vertex_buffer vbuf[2];
+ struct pipe_index_buffer ibuf;
void *handle;
memset(ve, 0, sizeof ve);
@@ -151,11 +152,14 @@ static void set_vertices( void )
ctx->set_vertex_buffers(ctx, 2, vbuf);
/* index data */
- indexBuffer = screen->user_buffer_create(screen,
+ ibuf.buffer = screen->user_buffer_create(screen,
indices,
sizeof(indices),
PIPE_BIND_VERTEX_BUFFER);
+ ibuf.offset = 0;
+ ibuf.index_size = 2;
+ ctx->set_index_buffer(ctx, &ibuf);
}
@@ -195,18 +199,19 @@ static void set_fragment_shader( void )
static void draw( void )
{
float clear_color[4] = {1,0,1,1};
+ struct pipe_draw_info info;
ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
+ util_draw_init_info(&info);
+ info.indexed = (draw_elements != 0);
+ info.mode = PIPE_PRIM_TRIANGLES;
+ info.start = 0;
+ info.count = 3;
/* draw NUM_INST triangles */
- if (draw_elements)
- ctx->draw_elements_instanced(ctx, indexBuffer, 2,
- 0, /* indexBias */
- PIPE_PRIM_TRIANGLES,
- 0, 3, /* start, count */
- 0, NUM_INST); /* startInst, instCount */
- else
- ctx->draw_arrays_instanced(ctx, PIPE_PRIM_TRIANGLES, 0, 3, 0, NUM_INST);
+ info.instance_count = NUM_INST;
+
+ ctx->draw_vbo(ctx, &info);
ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
diff --git a/src/gallium/tests/graw/tri.c b/src/gallium/tests/graw/tri.c
index 80377f526d..4dbd2c062a 100644
--- a/src/gallium/tests/graw/tri.c
+++ b/src/gallium/tests/graw/tri.c
@@ -10,6 +10,7 @@
#include "util/u_debug.h" /* debug_dump_surface_bmp() */
#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
enum pipe_format formats[] = {
PIPE_FORMAT_R8G8B8A8_UNORM,
@@ -134,7 +135,7 @@ static void draw( void )
float clear_color[4] = {1,0,1,1};
ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
- ctx->draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
+ util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
#if 0
diff --git a/src/gallium/tests/graw/vs-test.c b/src/gallium/tests/graw/vs-test.c
index 7f93db42c0..e1cd814bf7 100644
--- a/src/gallium/tests/graw/vs-test.c
+++ b/src/gallium/tests/graw/vs-test.c
@@ -14,6 +14,7 @@
#include "util/u_debug.h" /* debug_dump_surface_bmp() */
#include "util/u_inlines.h"
#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
#include "util/u_box.h"
static const char *filename = NULL;
@@ -226,7 +227,7 @@ static void draw( void )
float clear_color[4] = {.1,.3,.5,0};
ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
- ctx->draw_arrays(ctx, PIPE_PRIM_POINTS, 0, Elements(vertices));
+ util_draw_arrays(ctx, PIPE_PRIM_POINTS, 0, Elements(vertices));
ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
#if 0
diff --git a/src/gallium/tests/unit/Makefile b/src/gallium/tests/unit/Makefile
index f65958dadd..345bd1f694 100644
--- a/src/gallium/tests/unit/Makefile
+++ b/src/gallium/tests/unit/Makefile
@@ -22,7 +22,8 @@ SOURCES = \
pipe_barrier_test.c \
u_cache_test.c \
u_half_test.c \
- u_format_test.c
+ u_format_test.c \
+ translate_test.c
OBJECTS = $(SOURCES:.c=.o)
diff --git a/src/gallium/tests/unit/SConscript b/src/gallium/tests/unit/SConscript
index 8a9f3504c7..edc68e34d9 100644
--- a/src/gallium/tests/unit/SConscript
+++ b/src/gallium/tests/unit/SConscript
@@ -4,11 +4,18 @@ env = env.Clone()
env.Prepend(LIBS = [gallium])
+if platform in ('freebsd8', 'sunos5'):
+ env.Append(LIBS = ['m'])
+
+if platform == 'freebsd8':
+ env.Append(LIBS = ['pthread'])
+
progs = [
'pipe_barrier_test',
'u_cache_test',
'u_format_test',
- 'u_half_test'
+ 'u_half_test',
+ 'translate_test'
]
for prog in progs:
diff --git a/src/gallium/tests/unit/translate_test.c b/src/gallium/tests/unit/translate_test.c
new file mode 100644
index 0000000000..d0946a91a2
--- /dev/null
+++ b/src/gallium/tests/unit/translate_test.c
@@ -0,0 +1,310 @@
+/**************************************************************************
+ *
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 <stdio.h>
+#include <translate/translate.h>
+#include <util/u_memory.h>
+#include <util/u_format.h>
+#include <util/u_cpu_detect.h>
+#include <rtasm/rtasm_cpu.h>
+
+/* don't use this for serious use */
+static double rand_double()
+{
+ const double rm = (double)RAND_MAX + 1;
+ double div = 1;
+ double v = 0;
+ unsigned i;
+ for(i = 0; i < 4; ++i)
+ {
+ div *= rm;
+ v += (double)rand() / div;
+ }
+ return v;
+}
+
+int main(int argc, char** argv)
+{
+ struct translate *(*create_fn)(const struct translate_key *key) = 0;
+
+ struct translate_key key;
+ unsigned output_format;
+ unsigned input_format;
+ unsigned buffer_size = 4096;
+ unsigned char* buffer[5];
+ unsigned char* byte_buffer;
+ float* float_buffer;
+ double* double_buffer;
+ unsigned count = 4;
+ unsigned i, j, k;
+ unsigned passed = 0;
+ unsigned total = 0;
+ const float error = 0.03125;
+
+ create_fn = 0;
+
+ util_cpu_detect();
+
+ if(argc <= 1)
+ {}
+ else if (!strcmp(argv[1], "generic"))
+ create_fn = translate_generic_create;
+ else if (!strcmp(argv[1], "x86"))
+ create_fn = translate_sse2_create;
+ else if (!strcmp(argv[1], "nosse"))
+ {
+ util_cpu_caps.has_sse = 0;
+ util_cpu_caps.has_sse2 = 0;
+ util_cpu_caps.has_sse3 = 0;
+ util_cpu_caps.has_sse4_1 = 0;
+ create_fn = translate_sse2_create;
+ }
+ else if (!strcmp(argv[1], "sse"))
+ {
+ if(!util_cpu_caps.has_sse || !rtasm_cpu_has_sse())
+ {
+ printf("Error: CPU doesn't support SSE (test with qemu)\n");
+ return 2;
+ }
+ util_cpu_caps.has_sse2 = 0;
+ util_cpu_caps.has_sse3 = 0;
+ util_cpu_caps.has_sse4_1 = 0;
+ create_fn = translate_sse2_create;
+ }
+ else if (!strcmp(argv[1], "sse2"))
+ {
+ if(!util_cpu_caps.has_sse2 || !rtasm_cpu_has_sse())
+ {
+ printf("Error: CPU doesn't support SSE2 (test with qemu)\n");
+ return 2;
+ }
+ util_cpu_caps.has_sse3 = 0;
+ util_cpu_caps.has_sse4_1 = 0;
+ create_fn = translate_sse2_create;
+ }
+ else if (!strcmp(argv[1], "sse3"))
+ {
+ if(!util_cpu_caps.has_sse3 || !rtasm_cpu_has_sse())
+ {
+ printf("Error: CPU doesn't support SSE3 (test with qemu)\n");
+ return 2;
+ }
+ util_cpu_caps.has_sse4_1 = 0;
+ create_fn = translate_sse2_create;
+ }
+ else if (!strcmp(argv[1], "sse4.1"))
+ {
+ if(!util_cpu_caps.has_sse4_1 || !rtasm_cpu_has_sse())
+ {
+ printf("Error: CPU doesn't support SSE4.1 (test with qemu)\n");
+ return 2;
+ }
+ create_fn = translate_sse2_create;
+ }
+
+ if (!create_fn)
+ {
+ printf("Usage: ./translate_test [generic|x86|nosse|sse|sse2|sse3|sse4.1]\n");
+ return 2;
+ }
+
+ for (i = 1; i < Elements(buffer); ++i)
+ buffer[i] = align_malloc(buffer_size, 4096);
+
+ byte_buffer = align_malloc(buffer_size, 4096);
+ float_buffer = align_malloc(buffer_size, 4096);
+ double_buffer = align_malloc(buffer_size, 4096);
+
+ key.nr_elements = 1;
+ key.element[0].input_buffer = 0;
+ key.element[0].input_offset = 0;
+ key.element[0].output_offset = 0;
+ key.element[0].type = TRANSLATE_ELEMENT_NORMAL;
+ key.element[0].instance_divisor = 0;
+
+ srand(4359025);
+
+ /* avoid negative values that work badly when converted to unsigned format*/
+ for (i = 0; i < buffer_size; ++i)
+ byte_buffer[i] = rand() & 0x7f7f7f7f;
+
+ for (i = 0; i < buffer_size / sizeof(float); ++i)
+ float_buffer[i] = (float)rand_double();
+
+ for (i = 0; i < buffer_size / sizeof(double); ++i)
+ double_buffer[i] = rand_double();
+
+ for (output_format = 1; output_format < PIPE_FORMAT_COUNT; ++output_format)
+ {
+ const struct util_format_description* output_format_desc = util_format_description(output_format);
+ unsigned output_format_size;
+ unsigned output_normalized = 0;
+
+ if (!output_format_desc
+ || !output_format_desc->fetch_rgba_float
+ || !output_format_desc->pack_rgba_float
+ || output_format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB
+ || output_format_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN
+ || !translate_is_output_format_supported(output_format))
+ continue;
+
+ for(i = 0; i < output_format_desc->nr_channels; ++i)
+ {
+ if(output_format_desc->channel[i].type != UTIL_FORMAT_TYPE_FLOAT)
+ output_normalized |= (1 << output_format_desc->channel[i].normalized);
+ }
+
+ output_format_size = util_format_get_stride(output_format, 1);
+
+ for (input_format = 1; input_format < PIPE_FORMAT_COUNT; ++input_format)
+ {
+ const struct util_format_description* input_format_desc = util_format_description(input_format);
+ unsigned input_format_size;
+ struct translate* translate[2];
+ unsigned fail = 0;
+ unsigned used_generic = 0;
+ unsigned input_normalized = 0;
+ boolean input_is_float = FALSE;
+
+ if (!input_format_desc
+ || !input_format_desc->fetch_rgba_float
+ || !input_format_desc->pack_rgba_float
+ || input_format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB
+ || input_format_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN
+ || !translate_is_output_format_supported(input_format))
+ continue;
+
+ input_format_size = util_format_get_stride(input_format, 1);
+
+ for(i = 0; i < input_format_desc->nr_channels; ++i)
+ {
+ if(input_format_desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)
+ {
+ input_is_float = 1;
+ input_normalized |= 1 << 1;
+ }
+ else
+ input_normalized |= (1 << input_format_desc->channel[i].normalized);
+ }
+
+ if(((input_normalized | output_normalized) == 3)
+ || ((input_normalized & 1) && (output_normalized & 1)
+ && input_format_size * output_format_desc->nr_channels > output_format_size * input_format_desc->nr_channels))
+ continue;
+
+ key.element[0].input_format = input_format;
+ key.element[0].output_format = output_format;
+ key.output_stride = output_format_size;
+ translate[0] = create_fn(&key);
+ if (!translate[0])
+ continue;
+
+ key.element[0].input_format = output_format;
+ key.element[0].output_format = input_format;
+ key.output_stride = input_format_size;
+ translate[1] = create_fn(&key);
+ if(!translate[1])
+ {
+ used_generic = 1;
+ translate[1] = translate_generic_create(&key);
+ if(!translate[1])
+ continue;
+ }
+
+ for(i = 1; i < 5; ++i)
+ memset(buffer[i], 0xcd - (0x22 * i), 4096);
+
+ if(input_is_float && input_format_desc->channel[0].size == 32)
+ buffer[0] = (unsigned char*)float_buffer;
+ else if(input_is_float && input_format_desc->channel[0].size == 64)
+ buffer[0] = (unsigned char*)double_buffer;
+ else if(input_is_float)
+ abort();
+ else
+ buffer[0] = byte_buffer;
+
+ translate[0]->set_buffer(translate[0], 0, buffer[0], input_format_size, ~0);
+ translate[0]->run(translate[0], 0, count, 0, buffer[1]);
+ translate[1]->set_buffer(translate[1], 0, buffer[1], output_format_size, ~0);
+ translate[1]->run(translate[1], 0, count, 0, buffer[2]);
+ translate[0]->set_buffer(translate[0], 0, buffer[2], input_format_size, ~0);
+ translate[0]->run(translate[0], 0, count, 0, buffer[3]);
+ translate[1]->set_buffer(translate[1], 0, buffer[3], output_format_size, ~0);
+ translate[1]->run(translate[1], 0, count, 0, buffer[4]);
+
+ for (i = 0; i < count; ++i)
+ {
+ float a[4];
+ float b[4];
+ input_format_desc->fetch_rgba_float(a, buffer[2] + i * input_format_size, 0, 0);
+ input_format_desc->fetch_rgba_float(b, buffer[4] + i * input_format_size, 0, 0);
+
+ for (j = 0; j < count; ++j)
+ {
+ float d = a[j] - b[j];
+ if (d > error || d < -error)
+ {
+ fail = 1;
+ break;
+ }
+ }
+ }
+
+ printf("%s%s: %s -> %s -> %s -> %s -> %s\n",
+ fail ? "FAIL" : "PASS",
+ used_generic ? "[GENERIC]" : "",
+ input_format_desc->name, output_format_desc->name, input_format_desc->name, output_format_desc->name, input_format_desc->name);
+
+ if (1)
+ {
+ for (i = 0; i < Elements(buffer); ++i)
+ {
+ unsigned format_size = (i & 1) ? output_format_size : input_format_size;
+ printf("%c ", (i == 2 || i == 4) ? '*' : ' ');
+ for (j = 0; j < count; ++j)
+ {
+ for (k = 0; k < format_size; ++k)
+ {
+ printf("%02x", buffer[i][j * format_size + k]);
+ }
+ printf(" ");
+ }
+ printf("\n");
+ }
+ }
+
+ if (!fail)
+ ++passed;
+ ++total;
+
+ if(translate[1])
+ translate[1]->release(translate[1]);
+ translate[0]->release(translate[0]);
+ }
+ }
+
+ printf("%u/%u tests passed for translate_%s\n", passed, total, argv[1]);
+ return passed != total;
+}
diff --git a/src/gallium/winsys/r600/drm/SConscript b/src/gallium/winsys/r600/drm/SConscript
new file mode 100644
index 0000000000..2f20d9f895
--- /dev/null
+++ b/src/gallium/winsys/r600/drm/SConscript
@@ -0,0 +1,25 @@
+Import('*')
+
+env = env.Clone()
+
+r600_sources = [
+ 'bof.c',
+ 'r600_state.c',
+ 'radeon_ctx.c',
+ 'radeon_draw.c',
+ 'radeon_state.c',
+ 'radeon_bo.c',
+ 'radeon_pciid.c',
+ 'radeon.c',
+ 'r600_drm.c'
+]
+
+env.ParseConfig('pkg-config --cflags libdrm_radeon')
+env.Append(CPPPATH = '#/src/gallium/drivers/r600')
+
+r600winsys = env.ConvenienceLibrary(
+ target ='r600winsys',
+ source = r600_sources,
+)
+
+Export('r600winsys')
diff --git a/src/gallium/winsys/r600/drm/r600_drm.c b/src/gallium/winsys/r600/drm/r600_drm.c
index 3d87a994c1..c76e7f5fa5 100644
--- a/src/gallium/winsys/r600/drm/r600_drm.c
+++ b/src/gallium/winsys/r600/drm/r600_drm.c
@@ -30,8 +30,7 @@
#include "util/u_debug.h"
#include "radeon_priv.h"
#include "r600_screen.h"
-#include "r600_texture.h"
-#include "r600_public.h"
+#include "r600_resource.h"
#include "r600_drm_public.h"
#include "state_tracker/drm_driver.h"
@@ -45,7 +44,7 @@ boolean r600_buffer_get_handle(struct radeon *rw,
struct winsys_handle *whandle)
{
struct drm_gem_flink flink;
- struct r600_buffer* rbuffer = (struct r600_buffer*)buf;
+ struct r600_resource* rbuffer = (struct r600_resource*)buf;
if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
if (!rbuffer->flink) {
diff --git a/src/gallium/winsys/r600/drm/r600_states.h b/src/gallium/winsys/r600/drm/r600_states.h
index 5896df21b2..e40c77d8f6 100644
--- a/src/gallium/winsys/r600/drm/r600_states.h
+++ b/src/gallium/winsys/r600/drm/r600_states.h
@@ -372,6 +372,76 @@ static const struct radeon_register R600_CB0_names[] = {
{0x00028100, 0, 0, "CB_COLOR0_MASK"},
};
+static const struct radeon_register R600_CB1_names[] = {
+ {0x00028044, 1, 0, "CB_COLOR1_BASE"},
+ {0x000280A4, 0, 0, "CB_COLOR1_INFO"},
+ {0x00028064, 0, 0, "CB_COLOR1_SIZE"},
+ {0x00028084, 0, 0, "CB_COLOR1_VIEW"},
+ {0x000280E4, 1, 1, "CB_COLOR1_FRAG"},
+ {0x000280C4, 1, 2, "CB_COLOR1_TILE"},
+ {0x00028104, 0, 0, "CB_COLOR1_MASK"},
+};
+
+static const struct radeon_register R600_CB2_names[] = {
+ {0x00028048, 1, 0, "CB_COLOR2_BASE"},
+ {0x000280A8, 0, 0, "CB_COLOR2_INFO"},
+ {0x00028068, 0, 0, "CB_COLOR2_SIZE"},
+ {0x00028088, 0, 0, "CB_COLOR2_VIEW"},
+ {0x000280E8, 1, 1, "CB_COLOR2_FRAG"},
+ {0x000280C8, 1, 2, "CB_COLOR2_TILE"},
+ {0x00028108, 0, 0, "CB_COLOR2_MASK"},
+};
+
+static const struct radeon_register R600_CB3_names[] = {
+ {0x0002804C, 1, 0, "CB_COLOR3_BASE"},
+ {0x000280AC, 0, 0, "CB_COLOR3_INFO"},
+ {0x0002806C, 0, 0, "CB_COLOR3_SIZE"},
+ {0x0002808C, 0, 0, "CB_COLOR3_VIEW"},
+ {0x000280EC, 1, 1, "CB_COLOR3_FRAG"},
+ {0x000280CC, 1, 2, "CB_COLOR3_TILE"},
+ {0x0002810C, 0, 0, "CB_COLOR3_MASK"},
+};
+
+static const struct radeon_register R600_CB4_names[] = {
+ {0x00028050, 1, 0, "CB_COLOR4_BASE"},
+ {0x000280B0, 0, 0, "CB_COLOR4_INFO"},
+ {0x00028070, 0, 0, "CB_COLOR4_SIZE"},
+ {0x00028090, 0, 0, "CB_COLOR4_VIEW"},
+ {0x000280F0, 1, 1, "CB_COLOR4_FRAG"},
+ {0x000280D0, 1, 2, "CB_COLOR4_TILE"},
+ {0x00028110, 0, 0, "CB_COLOR4_MASK"},
+};
+
+static const struct radeon_register R600_CB5_names[] = {
+ {0x00028054, 1, 0, "CB_COLOR5_BASE"},
+ {0x000280B4, 0, 0, "CB_COLOR5_INFO"},
+ {0x00028074, 0, 0, "CB_COLOR5_SIZE"},
+ {0x00028094, 0, 0, "CB_COLOR5_VIEW"},
+ {0x000280F4, 1, 1, "CB_COLOR5_FRAG"},
+ {0x000280D4, 1, 2, "CB_COLOR5_TILE"},
+ {0x00028114, 0, 0, "CB_COLOR5_MASK"},
+};
+
+static const struct radeon_register R600_CB6_names[] = {
+ {0x00028058, 1, 0, "CB_COLOR6_BASE"},
+ {0x000280B8, 0, 0, "CB_COLOR6_INFO"},
+ {0x00028078, 0, 0, "CB_COLOR6_SIZE"},
+ {0x00028098, 0, 0, "CB_COLOR6_VIEW"},
+ {0x000280F8, 1, 1, "CB_COLOR6_FRAG"},
+ {0x000280D8, 1, 2, "CB_COLOR6_TILE"},
+ {0x00028118, 0, 0, "CB_COLOR6_MASK"},
+};
+
+static const struct radeon_register R600_CB7_names[] = {
+ {0x0002805C, 1, 0, "CB_COLOR7_BASE"},
+ {0x000280BC, 0, 0, "CB_COLOR7_INFO"},
+ {0x0002807C, 0, 0, "CB_COLOR7_SIZE"},
+ {0x0002809C, 0, 0, "CB_COLOR7_VIEW"},
+ {0x000280FC, 1, 1, "CB_COLOR7_FRAG"},
+ {0x000280DC, 1, 2, "CB_COLOR7_TILE"},
+ {0x0002811C, 0, 0, "CB_COLOR7_MASK"},
+};
+
static const struct radeon_register R600_DB_names[] = {
{0x0002800C, 1, 0, "DB_DEPTH_BASE"},
{0x00028000, 0, 0, "DB_DEPTH_SIZE"},
@@ -425,9 +495,16 @@ static struct radeon_type R600_types[] = {
{ 128, 1233, 0x0000A600, 0x0000A720, 0x0010, 0, "R600_VS_SAMPLER_BORDER", 4, r600_state_pm4_generic, R600_VS_SAMPLER_BORDER_names},
{ 128, 1251, 0x0000A800, 0x0000A920, 0x0010, 0, "R600_GS_SAMPLER_BORDER", 4, r600_state_pm4_generic, R600_GS_SAMPLER_BORDER_names},
{ 128, 1269, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB0", 7, r600_state_pm4_cb0, R600_CB0_names},
- { 128, 1270, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, r600_state_pm4_db, R600_DB_names},
- { 128, 1271, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, r600_state_pm4_vgt, R600_VGT_names},
- { 128, 1272, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, r600_state_pm4_draw, R600_DRAW_names},
+ { 128, 1270, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB1", 7, r600_state_pm4_cb0, R600_CB1_names},
+ { 128, 1271, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB2", 7, r600_state_pm4_cb0, R600_CB2_names},
+ { 128, 1272, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB3", 7, r600_state_pm4_cb0, R600_CB3_names},
+ { 128, 1273, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB4", 7, r600_state_pm4_cb0, R600_CB4_names},
+ { 128, 1274, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB5", 7, r600_state_pm4_cb0, R600_CB5_names},
+ { 128, 1275, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB6", 7, r600_state_pm4_cb0, R600_CB6_names},
+ { 128, 1276, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB7", 7, r600_state_pm4_cb0, R600_CB7_names},
+ { 128, 1277, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, r600_state_pm4_db, R600_DB_names},
+ { 128, 1278, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, r600_state_pm4_vgt, R600_VGT_names},
+ { 128, 1279, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, r600_state_pm4_draw, R600_DRAW_names},
};
static struct radeon_type R700_types[] = {
@@ -453,9 +530,16 @@ static struct radeon_type R700_types[] = {
{ 128, 1233, 0x0000A600, 0x0000A720, 0x0010, 0, "R600_VS_SAMPLER_BORDER", 4, r600_state_pm4_generic, R600_VS_SAMPLER_BORDER_names},
{ 128, 1251, 0x0000A800, 0x0000A920, 0x0010, 0, "R600_GS_SAMPLER_BORDER", 4, r600_state_pm4_generic, R600_GS_SAMPLER_BORDER_names},
{ 128, 1269, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB0", 7, r700_state_pm4_cb0, R600_CB0_names},
- { 128, 1270, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, r700_state_pm4_db, R600_DB_names},
- { 128, 1271, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, r600_state_pm4_vgt, R600_VGT_names},
- { 128, 1272, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, r600_state_pm4_draw, R600_DRAW_names},
+ { 128, 1270, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB1", 7, r600_state_pm4_cb0, R600_CB1_names},
+ { 128, 1271, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB2", 7, r600_state_pm4_cb0, R600_CB2_names},
+ { 128, 1272, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB3", 7, r600_state_pm4_cb0, R600_CB3_names},
+ { 128, 1273, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB4", 7, r600_state_pm4_cb0, R600_CB4_names},
+ { 128, 1274, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB5", 7, r600_state_pm4_cb0, R600_CB5_names},
+ { 128, 1275, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB6", 7, r600_state_pm4_cb0, R600_CB6_names},
+ { 128, 1276, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB7", 7, r600_state_pm4_cb0, R600_CB7_names},
+ { 128, 1277, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, r700_state_pm4_db, R600_DB_names},
+ { 128, 1278, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, r600_state_pm4_vgt, R600_VGT_names},
+ { 128, 1279, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, r600_state_pm4_draw, R600_DRAW_names},
};
#endif
diff --git a/src/gallium/winsys/r600/drm/radeon.c b/src/gallium/winsys/r600/drm/radeon.c
index 7e65669806..80b0a1d397 100644
--- a/src/gallium/winsys/r600/drm/radeon.c
+++ b/src/gallium/winsys/r600/drm/radeon.c
@@ -23,7 +23,6 @@
#include "xf86drm.h"
#include "radeon_priv.h"
#include "radeon_drm.h"
-#include "r600d.h"
enum radeon_family radeon_get_family(struct radeon *radeon)
{
diff --git a/src/gallium/winsys/r600/drm/radeon_ctx.c b/src/gallium/winsys/r600/drm/radeon_ctx.c
index 6b0eba0b28..45b706bb0f 100644
--- a/src/gallium/winsys/r600/drm/radeon_ctx.c
+++ b/src/gallium/winsys/r600/drm/radeon_ctx.c
@@ -112,6 +112,7 @@ struct radeon_ctx *radeon_ctx_decref(struct radeon_ctx *ctx)
ctx->bo[i] = radeon_bo_decref(ctx->radeon, ctx->bo[i]);
}
ctx->radeon = radeon_decref(ctx->radeon);
+ free(ctx->state);
free(ctx->draw);
free(ctx->bo);
free(ctx->pm4);
@@ -151,6 +152,8 @@ int radeon_ctx_submit(struct radeon_ctx *ctx)
uint64_t chunk_array[2];
int r = 0;
+ if (!ctx->cpm4)
+ return 0;
#if 0
for (r = 0; r < ctx->cpm4; r++) {
fprintf(stderr, "0x%08X\n", ctx->pm4[r]);
diff --git a/src/gallium/winsys/r600/drm/radeon_priv.h b/src/gallium/winsys/r600/drm/radeon_priv.h
index b91421f438..96c0d060f7 100644
--- a/src/gallium/winsys/r600/drm/radeon_priv.h
+++ b/src/gallium/winsys/r600/drm/radeon_priv.h
@@ -68,36 +68,6 @@ extern int radeon_is_family_compatible(unsigned family1, unsigned family2);
extern int radeon_reg_id(struct radeon *radeon, unsigned offset, unsigned *typeid, unsigned *stateid, unsigned *id);
extern unsigned radeon_type_from_id(struct radeon *radeon, unsigned id);
-/*
- * radeon context functions
- */
-#pragma pack(1)
-struct radeon_cs_reloc {
- uint32_t handle;
- uint32_t read_domain;
- uint32_t write_domain;
- uint32_t flags;
-};
-#pragma pack()
-
-struct radeon_ctx {
- int refcount;
- struct radeon *radeon;
- u32 *pm4;
- u32 cpm4;
- u32 draw_cpm4;
- unsigned id;
- unsigned next_id;
- unsigned nreloc;
- struct radeon_cs_reloc *reloc;
- unsigned nbo;
- struct radeon_bo **bo;
- unsigned ndraw;
- struct radeon_draw *cdraw;
- struct radeon_draw **draw;
- unsigned nstate;
- struct radeon_state **state;
-};
int radeon_ctx_set_bo_new(struct radeon_ctx *ctx, struct radeon_bo *bo);
struct radeon_bo *radeon_ctx_get_bo(struct radeon_ctx *ctx, unsigned reloc);
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm.c b/src/gallium/winsys/radeon/drm/radeon_drm.c
index e9a276362f..86d4f94969 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm.c
@@ -39,7 +39,6 @@
#include "util/u_memory.h"
#include "xf86drm.h"
-#include <sys/ioctl.h>
static struct radeon_libdrm_winsys *
radeon_winsys_create(int fd)
@@ -55,6 +54,31 @@ radeon_winsys_create(int fd)
return rws;
}
+/* Enable/disable Hyper-Z access. Return TRUE on success. */
+static boolean radeon_set_hyperz_access(int fd, boolean enable)
+{
+#ifndef RADEON_INFO_WANT_HYPERZ
+#define RADEON_INFO_WANT_HYPERZ 7
+#endif
+
+ struct drm_radeon_info info = {0};
+ unsigned value = enable ? 1 : 0;
+
+ if (!debug_get_bool_option("RADEON_HYPERZ", FALSE))
+ return FALSE;
+
+ info.value = (unsigned long)&value;
+ info.request = RADEON_INFO_WANT_HYPERZ;
+
+ if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0)
+ return FALSE;
+
+ if (enable && !value)
+ return FALSE;
+
+ return TRUE;
+}
+
/* Helper function to do the ioctls needed for setup and init. */
static void do_ioctls(int fd, struct radeon_libdrm_winsys* winsys)
{
@@ -103,6 +127,10 @@ static void do_ioctls(int fd, struct radeon_libdrm_winsys* winsys)
winsys->drm_2_3_0 = version->version_major > 2 ||
version->version_minor >= 3;
+ winsys->drm_2_6_0 = version->version_major > 2 ||
+ (version->version_major == 2 &&
+ version->version_minor >= 6);
+
info.request = RADEON_INFO_DEVICE_ID;
retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
if (retval) {
@@ -130,6 +158,8 @@ static void do_ioctls(int fd, struct radeon_libdrm_winsys* winsys)
}
winsys->z_pipes = target;
+ winsys->hyperz = radeon_set_hyperz_access(fd, TRUE);
+
retval = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO,
&gem_info, sizeof(gem_info));
if (retval) {
@@ -142,12 +172,14 @@ static void do_ioctls(int fd, struct radeon_libdrm_winsys* winsys)
debug_printf("radeon: Successfully grabbed chipset info from kernel!\n"
"radeon: DRM version: %d.%d.%d ID: 0x%04x GB: %d Z: %d\n"
- "radeon: GART size: %d MB VRAM size: %d MB\n",
+ "radeon: GART size: %d MB VRAM size: %d MB\n"
+ "radeon: HyperZ: %s\n",
version->version_major, version->version_minor,
version->version_patchlevel, winsys->pci_id,
winsys->gb_pipes, winsys->z_pipes,
winsys->gart_size / 1024 / 1024,
- winsys->vram_size / 1024 / 1024);
+ winsys->vram_size / 1024 / 1024,
+ winsys->hyperz ? "YES" : "NO");
drmFreeVersion(version);
}
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
index 5ea5912089..017eac8464 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
@@ -189,7 +189,7 @@ struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager
pipe_reference_init(&buf->base.base.reference, 1);
buf->base.base.alignment = 0;
buf->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
- buf->base.base.size = 0;
+ buf->base.base.size = bo->size;
buf->base.vtbl = &radeon_drm_buffer_vtbl;
buf->mgr = mgr;
diff --git a/src/gallium/winsys/radeon/drm/radeon_r300.c b/src/gallium/winsys/radeon/drm/radeon_r300.c
index effa27f5c7..5840098642 100644
--- a/src/gallium/winsys/radeon/drm/radeon_r300.c
+++ b/src/gallium/winsys/radeon/drm/radeon_r300.c
@@ -109,14 +109,19 @@ static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws,
struct winsys_handle *whandle,
- unsigned *stride)
+ unsigned *stride,
+ unsigned *size)
{
struct radeon_libdrm_winsys *ws = radeon_libdrm_winsys(rws);
struct pb_buffer *_buf;
- *stride = whandle->stride;
-
_buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle);
+
+ if (stride)
+ *stride = whandle->stride;
+ if (size)
+ *size = _buf->base.size;
+
return radeon_libdrm_winsys_buffer(_buf);
}
@@ -206,6 +211,10 @@ static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
return ws->squaretiling;
case R300_VID_DRM_2_3_0:
return ws->drm_2_3_0;
+ case R300_VID_DRM_2_6_0:
+ return ws->drm_2_6_0;
+ case R300_CAN_HYPERZ:
+ return ws->hyperz;
}
return 0;
}
diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h
index 533b7b2e2d..6f4aa4bce3 100644
--- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
+++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
@@ -65,6 +65,15 @@ struct radeon_libdrm_winsys {
*/
boolean drm_2_3_0;
+ /* DRM 2.6.0
+ * - Hyper-Z
+ * - GB_Z_PEQ_CONFIG allowed on rv350->r4xx, we should initialize it
+ */
+ boolean drm_2_6_0;
+
+ /* hyperz user */
+ boolean hyperz;
+
/* DRM FD */
int fd;
diff --git a/src/gallium/winsys/svga/drm/vmw_screen_dri.c b/src/gallium/winsys/svga/drm/vmw_screen_dri.c
index 1b0d10f60d..7bd4407e9f 100644
--- a/src/gallium/winsys/svga/drm/vmw_screen_dri.c
+++ b/src/gallium/winsys/svga/drm/vmw_screen_dri.c
@@ -32,8 +32,6 @@
#include "vmw_screen.h"
#include "vmw_surface.h"
-#include "vmw_fence.h"
-#include "vmw_context.h"
#include "svga_drm_public.h"
#include "state_tracker/drm_driver.h"